mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:47:30 +02:00
Merge branch 'master' into scriptvec3
This commit is contained in:
commit
e3543cf098
59 changed files with 578 additions and 798 deletions
|
@ -88,7 +88,7 @@ if (APPLE)
|
|||
set(OSX_SDK "${OSX_VERSION}" CACHE String "OS X SDK version to look for inside Xcode bundle or at OSX_SDK_PATH")
|
||||
|
||||
# set our OS X deployment target
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
|
||||
|
||||
# find the SDK path for the desired SDK
|
||||
find_path(
|
||||
|
|
14
cmake/externals/quazip/CMakeLists.txt
vendored
14
cmake/externals/quazip/CMakeLists.txt
vendored
|
@ -1,14 +1,12 @@
|
|||
set(EXTERNAL_NAME quazip)
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
cmake_policy(SET CMP0046 OLD)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
set(QUAZIP_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=<INSTALL_DIR>/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON)
|
||||
|
||||
if (APPLE)
|
||||
else ()
|
||||
set(QUAZIP_CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11)
|
||||
if (NOT APPLE)
|
||||
set(QUAZIP_CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} -DCMAKE_CXX_STANDARD=11)
|
||||
endif ()
|
||||
|
||||
ExternalProject_Add(
|
||||
|
@ -22,10 +20,12 @@ ExternalProject_Add(
|
|||
LOG_BUILD 1
|
||||
)
|
||||
|
||||
add_dependencies(quazip zlib)
|
||||
if (WIN32)
|
||||
add_dependencies(quazip zlib)
|
||||
endif ()
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES
|
||||
FOLDER "hidden/externals"
|
||||
INSTALL_NAME_DIR ${INSTALL_DIR}/lib
|
||||
BUILD_WITH_INSTALL_RPATH True)
|
||||
|
@ -54,4 +54,4 @@ select_library_configurations(${EXTERNAL_NAME_UPPER})
|
|||
|
||||
# Force selected libraries into the cache
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${${EXTERNAL_NAME_UPPER}_LIBRARY} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${${EXTERNAL_NAME_UPPER}_LIBRARIES} CACHE FILEPATH "Location of QuaZip libraries")
|
||||
|
|
|
@ -3,11 +3,11 @@ if (WIN32)
|
|||
endif (WIN32)
|
||||
|
||||
if (POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 OLD)
|
||||
cmake_policy(SET CMP0043 NEW)
|
||||
endif ()
|
||||
|
||||
if (POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif ()
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
@ -34,7 +34,7 @@ file(GLOB HIFI_CUSTOM_MACROS "cmake/macros/*.cmake")
|
|||
foreach(CUSTOM_MACRO ${HIFI_CUSTOM_MACROS})
|
||||
include(${CUSTOM_MACRO})
|
||||
endforeach()
|
||||
unset(HIFI_CUSTOM_MACROS)
|
||||
unset(HIFI_CUSTOM_MACROS)
|
||||
|
||||
if (ANDROID)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#
|
||||
#
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
# Created by Bradley Austin Davis on 2015/10/10
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
#
|
||||
macro(TARGET_ZLIB)
|
||||
|
||||
if (WIN32)
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 548 KiB |
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"compressed": {
|
||||
"COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT": "Default-Sky-9-cubemap_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT.ktx",
|
||||
"COMPRESSED_SRGB8_ETC2": "Default-Sky-9-cubemap_COMPRESSED_SRGB8_ETC2.ktx"
|
||||
},
|
||||
"original": "Default-Sky-9-cubemap.jpg",
|
||||
"uncompressed": "Default-Sky-9-cubemap.ktx"
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -152,6 +152,8 @@
|
|||
#include <avatars-renderer/ScriptAvatar.h>
|
||||
#include <RenderableEntityItem.h>
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
#include <model-networking/MaterialCache.h>
|
||||
#include "recording/ClipCache.h"
|
||||
|
||||
#include "AudioClient.h"
|
||||
#include "audio/AudioScope.h"
|
||||
|
@ -328,9 +330,9 @@ static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains
|
|||
#endif
|
||||
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
|
||||
static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16;
|
||||
#else
|
||||
static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
|
||||
static const uint32_t MAX_CONCURRENT_RESOURCE_DOWNLOADS = 4;
|
||||
#endif
|
||||
|
||||
// For processing on QThreadPool, we target a number of threads after reserving some
|
||||
|
@ -1327,7 +1329,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
|
||||
bool success;
|
||||
int concurrentDownloads = concurrentDownloadsStr.toInt(&success);
|
||||
uint32_t concurrentDownloads = concurrentDownloadsStr.toUInt(&success);
|
||||
if (!success) {
|
||||
concurrentDownloads = MAX_CONCURRENT_RESOURCE_DOWNLOADS;
|
||||
}
|
||||
|
@ -2054,7 +2056,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
}
|
||||
|
||||
properties["active_downloads"] = loadingRequests.size();
|
||||
properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
|
||||
properties["pending_downloads"] = (int)ResourceCache::getPendingRequestCount();
|
||||
properties["active_downloads_details"] = loadingRequestsStats;
|
||||
|
||||
auto statTracker = DependencyManager::get<StatTracker>();
|
||||
|
@ -4653,8 +4655,8 @@ void Application::idle() {
|
|||
PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());
|
||||
}
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", int, ResourceCache::getLoadingRequests().length());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", uint32_t, ResourceCache::getLoadingRequestCount());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", uint32_t, ResourceCache::getPendingRequestCount());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
|
||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
|
||||
auto renderConfig = _renderEngine->getConfiguration();
|
||||
|
@ -5399,13 +5401,21 @@ void Application::reloadResourceCaches() {
|
|||
|
||||
queryOctree(NodeType::EntityServer, PacketType::EntityQuery);
|
||||
|
||||
// Clear the entities and their renderables
|
||||
getEntities()->clear();
|
||||
|
||||
DependencyManager::get<AssetClient>()->clearCache();
|
||||
DependencyManager::get<ScriptCache>()->clearCache();
|
||||
|
||||
// Clear all the resource caches
|
||||
DependencyManager::get<ResourceCacheSharedItems>()->clear();
|
||||
DependencyManager::get<AnimationCache>()->refreshAll();
|
||||
DependencyManager::get<ModelCache>()->refreshAll();
|
||||
DependencyManager::get<SoundCache>()->refreshAll();
|
||||
MaterialCache::instance().refreshAll();
|
||||
DependencyManager::get<ModelCache>()->refreshAll();
|
||||
ShaderCache::instance().refreshAll();
|
||||
DependencyManager::get<TextureCache>()->refreshAll();
|
||||
DependencyManager::get<recording::ClipCache>()->refreshAll();
|
||||
|
||||
DependencyManager::get<NodeList>()->reset(); // Force redownload of .fst models
|
||||
|
||||
|
@ -6470,9 +6480,12 @@ void Application::clearDomainOctreeDetails() {
|
|||
skyStage->setBackgroundMode(graphics::SunSkyStage::SKY_DEFAULT);
|
||||
|
||||
DependencyManager::get<AnimationCache>()->clearUnusedResources();
|
||||
DependencyManager::get<ModelCache>()->clearUnusedResources();
|
||||
DependencyManager::get<SoundCache>()->clearUnusedResources();
|
||||
MaterialCache::instance().clearUnusedResources();
|
||||
DependencyManager::get<ModelCache>()->clearUnusedResources();
|
||||
ShaderCache::instance().clearUnusedResources();
|
||||
DependencyManager::get<TextureCache>()->clearUnusedResources();
|
||||
DependencyManager::get<recording::ClipCache>()->clearUnusedResources();
|
||||
|
||||
getMyAvatar()->setAvatarEntityDataChanged(true);
|
||||
}
|
||||
|
|
|
@ -1942,7 +1942,7 @@ void MyAvatar::updateMotors() {
|
|||
horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE;
|
||||
verticalMotorTimescale = FLYING_MOTOR_TIMESCALE;
|
||||
} else {
|
||||
horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE;
|
||||
horizontalMotorTimescale = WALKING_MOTOR_TIMESCALE * getSensorToWorldScale();
|
||||
verticalMotorTimescale = INVALID_MOTOR_TIMESCALE;
|
||||
}
|
||||
|
||||
|
|
|
@ -267,8 +267,8 @@ void Stats::updateStats(bool force) {
|
|||
|
||||
auto loadingRequests = ResourceCache::getLoadingRequests();
|
||||
STAT_UPDATE(downloads, loadingRequests.size());
|
||||
STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit())
|
||||
STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount());
|
||||
STAT_UPDATE(downloadLimit, (int)ResourceCache::getRequestLimit())
|
||||
STAT_UPDATE(downloadsPending, (int)ResourceCache::getPendingRequestCount());
|
||||
STAT_UPDATE(processing, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
|
||||
STAT_UPDATE(processingPending, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
|
||||
|
||||
|
|
|
@ -32,12 +32,6 @@ AnimationCache::AnimationCache(QObject* parent) :
|
|||
}
|
||||
|
||||
AnimationPointer AnimationCache::getAnimation(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AnimationPointer result;
|
||||
BLOCKING_INVOKE_METHOD(this, "getAnimation",
|
||||
Q_RETURN_ARG(AnimationPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
return getResource(url).staticCast<Animation>();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,12 +30,6 @@ SoundCache::SoundCache(QObject* parent) :
|
|||
}
|
||||
|
||||
SharedSoundPointer SoundCache::getSound(const QUrl& url) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
SharedSoundPointer result;
|
||||
BLOCKING_INVOKE_METHOD(this, "getSound",
|
||||
Q_RETURN_ARG(SharedSoundPointer, result), Q_ARG(const QUrl&, url));
|
||||
return result;
|
||||
}
|
||||
return getResource(url).staticCast<Sound>();
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::getCollisionGeometryResource() {
|
||||
QUrl hullURL(getCompoundShapeURL());
|
||||
QUrl hullURL(getCollisionShapeURL());
|
||||
QUrlQuery queryArgs(hullURL);
|
||||
queryArgs.addQueryItem("collision-hull", "");
|
||||
hullURL.setQuery(queryArgs);
|
||||
|
@ -325,8 +325,9 @@ bool RenderableModelEntityItem::computeShapeFailedToLoad() {
|
|||
|
||||
void RenderableModelEntityItem::setShapeType(ShapeType type) {
|
||||
ModelEntityItem::setShapeType(type);
|
||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||
if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
if (!_compoundShapeResource && !getCollisionShapeURL().isEmpty()) {
|
||||
getCollisionGeometryResource();
|
||||
}
|
||||
} else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) {
|
||||
|
@ -352,18 +353,21 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
|||
bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
||||
ShapeType type = getShapeType();
|
||||
auto model = getModel();
|
||||
if (type == SHAPE_TYPE_COMPOUND) {
|
||||
if (!model || getCompoundShapeURL().isEmpty()) {
|
||||
auto shapeType = getShapeType();
|
||||
if (shapeType == SHAPE_TYPE_COMPOUND || shapeType == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
auto shapeURL = getCollisionShapeURL();
|
||||
|
||||
if (!model || shapeURL.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model->getURL().isEmpty()) {
|
||||
if (model->getURL().isEmpty() || !_dimensionsInitialized) {
|
||||
// we need a render geometry with a scale to proceed, so give up.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (model->isLoaded()) {
|
||||
if (!getCompoundShapeURL().isEmpty() && !_compoundShapeResource) {
|
||||
if (!shapeURL.isEmpty() && !_compoundShapeResource) {
|
||||
const_cast<RenderableModelEntityItem*>(this)->getCollisionGeometryResource();
|
||||
}
|
||||
|
||||
|
@ -518,7 +522,16 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto& meshes = model->getGeometry()->getMeshes();
|
||||
std::vector<std::shared_ptr<const graphics::Mesh>> meshes;
|
||||
if (type == SHAPE_TYPE_SIMPLE_COMPOUND) {
|
||||
auto& fbxMeshes = _compoundShapeResource->getFBXGeometry().meshes;
|
||||
meshes.reserve(fbxMeshes.size());
|
||||
for (auto& fbxMesh : fbxMeshes) {
|
||||
meshes.push_back(fbxMesh._mesh);
|
||||
}
|
||||
} else {
|
||||
meshes = model->getGeometry()->getMeshes();
|
||||
}
|
||||
int32_t numMeshes = (int32_t)(meshes.size());
|
||||
|
||||
const int MAX_ALLOWED_MESH_COUNT = 1000;
|
||||
|
@ -752,7 +765,7 @@ bool RenderableModelEntityItem::shouldBePhysical() const {
|
|||
auto model = getModel();
|
||||
// If we have a model, make sure it hasn't failed to download.
|
||||
// If it has, we'll report back that we shouldn't be physical so that physics aren't held waiting for us to be ready.
|
||||
if (model && getShapeType() == SHAPE_TYPE_COMPOUND && model->didCollisionGeometryRequestFail()) {
|
||||
if (model && (getShapeType() == SHAPE_TYPE_COMPOUND || getShapeType() == SHAPE_TYPE_SIMPLE_COMPOUND) && model->didCollisionGeometryRequestFail()) {
|
||||
return false;
|
||||
} else if (model && getShapeType() != SHAPE_TYPE_NONE && model->didVisualGeometryRequestFail()) {
|
||||
return false;
|
||||
|
|
|
@ -320,7 +320,7 @@ void ParticleEffectEntityRenderer::stepSimulation() {
|
|||
}
|
||||
|
||||
void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
||||
if (!_visible) {
|
||||
if (!_visible || !(_networkTexture && _networkTexture->isLoaded())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -328,11 +328,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
stepSimulation();
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
if (_networkTexture && _networkTexture->isLoaded()) {
|
||||
batch.setResourceTexture(0, _networkTexture->getGPUTexture());
|
||||
} else {
|
||||
batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
batch.setResourceTexture(0, _networkTexture->getGPUTexture());
|
||||
|
||||
Transform transform;
|
||||
// The particles are in world space, so the transform is unused, except for the rotation, which we use
|
||||
|
|
|
@ -551,6 +551,10 @@ QString ModelEntityItem::getCompoundShapeURL() const {
|
|||
return _compoundShapeURL.get();
|
||||
}
|
||||
|
||||
QString ModelEntityItem::getCollisionShapeURL() const {
|
||||
return getShapeType() == SHAPE_TYPE_COMPOUND ? getCompoundShapeURL() : getModelURL();
|
||||
}
|
||||
|
||||
void ModelEntityItem::setColor(const glm::u8vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_color = value;
|
||||
|
|
|
@ -69,6 +69,9 @@ public:
|
|||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
QString getCompoundShapeURL() const;
|
||||
|
||||
// Returns the URL used for the collision shape
|
||||
QString getCollisionShapeURL() const;
|
||||
|
||||
// model related properties
|
||||
virtual void setModelURL(const QString& url);
|
||||
virtual void setCompoundShapeURL(const QString& url);
|
||||
|
|
|
@ -75,8 +75,6 @@ protected:
|
|||
void makeLocalRequest();
|
||||
Q_INVOKABLE void handleLocalRequestCompleted();
|
||||
|
||||
virtual bool isCacheable() const override { return _loaded; }
|
||||
|
||||
Q_INVOKABLE virtual void downloadFinished(const QByteArray& data) override;
|
||||
|
||||
bool handleFailedRequest(ResourceRequest::Result result) override;
|
||||
|
|
|
@ -27,28 +27,35 @@
|
|||
#include "NetworkLogging.h"
|
||||
#include "NodeList.h"
|
||||
|
||||
|
||||
#define clamp(x, min, max) (((x) < (min)) ? (min) :\
|
||||
(((x) > (max)) ? (max) :\
|
||||
(x)))
|
||||
|
||||
void ResourceCacheSharedItems::appendActiveRequest(QWeakPointer<Resource> resource) {
|
||||
bool ResourceCacheSharedItems::appendRequest(QWeakPointer<Resource> resource) {
|
||||
Lock lock(_mutex);
|
||||
_loadingRequests.append(resource);
|
||||
if ((uint32_t)_loadingRequests.size() < _requestLimit) {
|
||||
_loadingRequests.append(resource);
|
||||
return true;
|
||||
} else {
|
||||
_pendingRequests.append(resource);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceCacheSharedItems::appendPendingRequest(QWeakPointer<Resource> resource) {
|
||||
void ResourceCacheSharedItems::setRequestLimit(uint32_t limit) {
|
||||
Lock lock(_mutex);
|
||||
_pendingRequests.append(resource);
|
||||
_requestLimit = limit;
|
||||
}
|
||||
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() {
|
||||
uint32_t ResourceCacheSharedItems::getRequestLimit() const {
|
||||
Lock lock(_mutex);
|
||||
return _requestLimit;
|
||||
}
|
||||
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getPendingRequests() const {
|
||||
QList<QSharedPointer<Resource>> result;
|
||||
Lock lock(_mutex);
|
||||
|
||||
foreach(QSharedPointer<Resource> resource, _pendingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
foreach (QWeakPointer<Resource> resource, _pendingRequests) {
|
||||
auto locked = resource.lock();
|
||||
if (locked) {
|
||||
result.append(locked);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,16 +67,12 @@ uint32_t ResourceCacheSharedItems::getPendingRequestsCount() const {
|
|||
return _pendingRequests.size();
|
||||
}
|
||||
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() {
|
||||
QList<QSharedPointer<Resource>> ResourceCacheSharedItems::getLoadingRequests() const {
|
||||
QList<QSharedPointer<Resource>> result;
|
||||
Lock lock(_mutex);
|
||||
|
||||
foreach(QSharedPointer<Resource> resource, _loadingRequests) {
|
||||
if (resource) {
|
||||
result.append(resource);
|
||||
}
|
||||
{
|
||||
Lock lock(_mutex);
|
||||
result = _loadingRequests;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -131,6 +134,11 @@ QSharedPointer<Resource> ResourceCacheSharedItems::getHighestPendingRequest() {
|
|||
return highestResource;
|
||||
}
|
||||
|
||||
void ResourceCacheSharedItems::clear() {
|
||||
Lock lock(_mutex);
|
||||
_pendingRequests.clear();
|
||||
_loadingRequests.clear();
|
||||
}
|
||||
|
||||
ScriptableResourceCache::ScriptableResourceCache(QSharedPointer<ResourceCache> resourceCache) {
|
||||
_resourceCache = resourceCache;
|
||||
|
@ -244,9 +252,7 @@ ResourceCache::ResourceCache(QObject* parent) : QObject(parent) {
|
|||
}
|
||||
}
|
||||
|
||||
ResourceCache::~ResourceCache() {
|
||||
clearUnusedResources();
|
||||
}
|
||||
ResourceCache::~ResourceCache() {}
|
||||
|
||||
void ResourceCache::clearATPAssets() {
|
||||
{
|
||||
|
@ -260,6 +266,7 @@ void ResourceCache::clearATPAssets() {
|
|||
if (auto strongRef = resource.lock()) {
|
||||
// Make sure the resource won't reinsert itself
|
||||
strongRef->setCache(nullptr);
|
||||
_totalResourcesSize -= strongRef->getBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,28 +276,18 @@ void ResourceCache::clearATPAssets() {
|
|||
for (auto& resource : _unusedResources.values()) {
|
||||
if (resource->getURL().scheme() == URL_SCHEME_ATP) {
|
||||
_unusedResources.remove(resource->getLRUKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
QWriteLocker locker(&_resourcesToBeGottenLock);
|
||||
auto it = _resourcesToBeGotten.begin();
|
||||
while (it != _resourcesToBeGotten.end()) {
|
||||
if (it->scheme() == URL_SCHEME_ATP) {
|
||||
it = _resourcesToBeGotten.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
_unusedResourcesSize -= resource->getBytes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resetResourceCounters();
|
||||
}
|
||||
|
||||
void ResourceCache::refreshAll() {
|
||||
// Clear all unused resources so we don't have to reload them
|
||||
clearUnusedResources();
|
||||
resetResourceCounters();
|
||||
resetUnusedResourceCounter();
|
||||
|
||||
QHash<QUrl, QWeakPointer<Resource>> resources;
|
||||
{
|
||||
|
@ -306,21 +303,6 @@ void ResourceCache::refreshAll() {
|
|||
}
|
||||
}
|
||||
|
||||
void ResourceCache::refresh(const QUrl& url) {
|
||||
QSharedPointer<Resource> resource;
|
||||
{
|
||||
QReadLocker locker(&_resourcesLock);
|
||||
resource = _resources.value(url).lock();
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
resource->refresh();
|
||||
} else {
|
||||
removeResource(url);
|
||||
resetResourceCounters();
|
||||
}
|
||||
}
|
||||
|
||||
QVariantList ResourceCache::getResourceList() {
|
||||
QVariantList list;
|
||||
if (QThread::currentThread() != thread()) {
|
||||
|
@ -338,12 +320,13 @@ QVariantList ResourceCache::getResourceList() {
|
|||
return list;
|
||||
}
|
||||
|
||||
void ResourceCache::setRequestLimit(int limit) {
|
||||
_requestLimit = limit;
|
||||
void ResourceCache::setRequestLimit(uint32_t limit) {
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
sharedItems->setRequestLimit(limit);
|
||||
|
||||
// Now go fill any new request spots
|
||||
while (attemptHighestPriorityRequest()) {
|
||||
// just keep looping until we reach the new limit or no more pending requests
|
||||
while (sharedItems->getLoadingRequestsCount() < limit && sharedItems->getPendingRequestsCount() > 0) {
|
||||
attemptHighestPriorityRequest();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,9 +364,9 @@ QSharedPointer<Resource> ResourceCache::getResource(const QUrl& url, const QUrl&
|
|||
}
|
||||
|
||||
void ResourceCache::setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize) {
|
||||
_unusedResourcesMaxSize = clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE);
|
||||
_unusedResourcesMaxSize = glm::clamp(unusedResourcesMaxSize, MIN_UNUSED_MAX_SIZE, MAX_UNUSED_MAX_SIZE);
|
||||
reserveUnusedResource(0);
|
||||
resetResourceCounters();
|
||||
resetUnusedResourceCounter();
|
||||
}
|
||||
|
||||
void ResourceCache::addUnusedResource(const QSharedPointer<Resource>& resource) {
|
||||
|
@ -391,18 +374,20 @@ void ResourceCache::addUnusedResource(const QSharedPointer<Resource>& resource)
|
|||
if (resource->getBytes() == 0 || resource->getBytes() > _unusedResourcesMaxSize) {
|
||||
resource->setCache(nullptr);
|
||||
removeResource(resource->getURL(), resource->getBytes());
|
||||
resetResourceCounters();
|
||||
resetTotalResourceCounter();
|
||||
return;
|
||||
}
|
||||
reserveUnusedResource(resource->getBytes());
|
||||
|
||||
resource->setLRUKey(++_lastLRUKey);
|
||||
_unusedResourcesSize += resource->getBytes();
|
||||
|
||||
resetResourceCounters();
|
||||
{
|
||||
QWriteLocker locker(&_unusedResourcesLock);
|
||||
_unusedResources.insert(resource->getLRUKey(), resource);
|
||||
_unusedResourcesSize += resource->getBytes();
|
||||
}
|
||||
|
||||
QWriteLocker locker(&_unusedResourcesLock);
|
||||
_unusedResources.insert(resource->getLRUKey(), resource);
|
||||
resetUnusedResourceCounter();
|
||||
}
|
||||
|
||||
void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resource) {
|
||||
|
@ -412,7 +397,7 @@ void ResourceCache::removeUnusedResource(const QSharedPointer<Resource>& resourc
|
|||
_unusedResourcesSize -= resource->getBytes();
|
||||
|
||||
locker.unlock();
|
||||
resetResourceCounters();
|
||||
resetUnusedResourceCounter();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,14 +430,19 @@ void ResourceCache::clearUnusedResources() {
|
|||
}
|
||||
_unusedResources.clear();
|
||||
}
|
||||
_unusedResourcesSize = 0;
|
||||
}
|
||||
|
||||
void ResourceCache::resetResourceCounters() {
|
||||
void ResourceCache::resetTotalResourceCounter() {
|
||||
{
|
||||
QReadLocker locker(&_resourcesLock);
|
||||
_numTotalResources = _resources.size();
|
||||
}
|
||||
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void ResourceCache::resetUnusedResourceCounter() {
|
||||
{
|
||||
QReadLocker locker(&_unusedResourcesLock);
|
||||
_numUnusedResources = _unusedResources.size();
|
||||
|
@ -461,6 +451,13 @@ void ResourceCache::resetResourceCounters() {
|
|||
emit dirty();
|
||||
}
|
||||
|
||||
void ResourceCache::resetResourceCounters() {
|
||||
resetTotalResourceCounter();
|
||||
resetUnusedResourceCounter();
|
||||
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void ResourceCache::removeResource(const QUrl& url, qint64 size) {
|
||||
QWriteLocker locker(&_resourcesLock);
|
||||
_resources.remove(url);
|
||||
|
@ -481,38 +478,34 @@ QList<QSharedPointer<Resource>> ResourceCache::getLoadingRequests() {
|
|||
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequests();
|
||||
}
|
||||
|
||||
int ResourceCache::getPendingRequestCount() {
|
||||
uint32_t ResourceCache::getPendingRequestCount() {
|
||||
return DependencyManager::get<ResourceCacheSharedItems>()->getPendingRequestsCount();
|
||||
}
|
||||
|
||||
int ResourceCache::getLoadingRequestCount() {
|
||||
uint32_t ResourceCache::getLoadingRequestCount() {
|
||||
return DependencyManager::get<ResourceCacheSharedItems>()->getLoadingRequestsCount();
|
||||
}
|
||||
|
||||
bool ResourceCache::attemptRequest(QSharedPointer<Resource> resource) {
|
||||
Q_ASSERT(!resource.isNull());
|
||||
|
||||
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
if (_requestsActive >= _requestLimit) {
|
||||
// wait until a slot becomes available
|
||||
sharedItems->appendPendingRequest(resource);
|
||||
return false;
|
||||
if (sharedItems->appendRequest(resource)) {
|
||||
resource->makeRequest();
|
||||
return true;
|
||||
}
|
||||
|
||||
++_requestsActive;
|
||||
sharedItems->appendActiveRequest(resource);
|
||||
resource->makeRequest();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResourceCache::requestCompleted(QWeakPointer<Resource> resource) {
|
||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||
|
||||
sharedItems->removeRequest(resource);
|
||||
--_requestsActive;
|
||||
|
||||
attemptHighestPriorityRequest();
|
||||
// Now go fill any new request spots
|
||||
while (sharedItems->getLoadingRequestsCount() < sharedItems->getRequestLimit() && sharedItems->getPendingRequestsCount() > 0) {
|
||||
attemptHighestPriorityRequest();
|
||||
}
|
||||
}
|
||||
|
||||
bool ResourceCache::attemptHighestPriorityRequest() {
|
||||
|
@ -521,10 +514,6 @@ bool ResourceCache::attemptHighestPriorityRequest() {
|
|||
return (resource && attemptRequest(resource));
|
||||
}
|
||||
|
||||
const int DEFAULT_REQUEST_LIMIT = 10;
|
||||
int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
|
||||
int ResourceCache::_requestsActive = 0;
|
||||
|
||||
static int requestID = 0;
|
||||
|
||||
Resource::Resource(const QUrl& url) :
|
||||
|
@ -550,7 +539,7 @@ void Resource::ensureLoading() {
|
|||
}
|
||||
|
||||
void Resource::setLoadPriority(const QPointer<QObject>& owner, float priority) {
|
||||
if (!(_failedToLoad)) {
|
||||
if (!_failedToLoad) {
|
||||
_loadPriorities.insert(owner, priority);
|
||||
}
|
||||
}
|
||||
|
@ -566,7 +555,7 @@ void Resource::setLoadPriorities(const QHash<QPointer<QObject>, float>& prioriti
|
|||
}
|
||||
|
||||
void Resource::clearLoadPriority(const QPointer<QObject>& owner) {
|
||||
if (!(_failedToLoad)) {
|
||||
if (!_failedToLoad) {
|
||||
_loadPriorities.remove(owner);
|
||||
}
|
||||
}
|
||||
|
@ -592,6 +581,7 @@ void Resource::refresh() {
|
|||
if (_request && !(_loaded || _failedToLoad)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_request) {
|
||||
_request->disconnect(this);
|
||||
_request->deleteLater();
|
||||
|
@ -613,7 +603,7 @@ void Resource::allReferencesCleared() {
|
|||
|
||||
if (_cache && isCacheable()) {
|
||||
// create and reinsert new shared pointer
|
||||
QSharedPointer<Resource> self(this, &Resource::allReferencesCleared);
|
||||
QSharedPointer<Resource> self(this, &Resource::deleter);
|
||||
setSelf(self);
|
||||
reinsert();
|
||||
|
||||
|
@ -623,7 +613,7 @@ void Resource::allReferencesCleared() {
|
|||
if (_cache) {
|
||||
// remove from the cache
|
||||
_cache->removeResource(getURL(), getBytes());
|
||||
_cache->resetResourceCounters();
|
||||
_cache->resetTotalResourceCounter();
|
||||
}
|
||||
|
||||
deleteLater();
|
||||
|
@ -732,6 +722,7 @@ void Resource::handleReplyFinished() {
|
|||
{ "from_cache", false },
|
||||
{ "size_mb", _bytesTotal / 1000000.0 }
|
||||
});
|
||||
ResourceCache::requestCompleted(_self);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,21 +66,25 @@ class ResourceCacheSharedItems : public Dependency {
|
|||
using Lock = std::unique_lock<Mutex>;
|
||||
|
||||
public:
|
||||
void appendPendingRequest(QWeakPointer<Resource> newRequest);
|
||||
void appendActiveRequest(QWeakPointer<Resource> newRequest);
|
||||
bool appendRequest(QWeakPointer<Resource> newRequest);
|
||||
void removeRequest(QWeakPointer<Resource> doneRequest);
|
||||
QList<QSharedPointer<Resource>> getPendingRequests();
|
||||
uint32_t getPendingRequestsCount() const;
|
||||
QList<QSharedPointer<Resource>> getLoadingRequests();
|
||||
void setRequestLimit(uint32_t limit);
|
||||
uint32_t getRequestLimit() const;
|
||||
QList<QSharedPointer<Resource>> getPendingRequests() const;
|
||||
QSharedPointer<Resource> getHighestPendingRequest();
|
||||
uint32_t getPendingRequestsCount() const;
|
||||
QList<QSharedPointer<Resource>> getLoadingRequests() const;
|
||||
uint32_t getLoadingRequestsCount() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
ResourceCacheSharedItems() = default;
|
||||
|
||||
mutable Mutex _mutex;
|
||||
QList<QWeakPointer<Resource>> _pendingRequests;
|
||||
QList<QWeakPointer<Resource>> _loadingRequests;
|
||||
QList<QSharedPointer<Resource>> _loadingRequests;
|
||||
const uint32_t DEFAULT_REQUEST_LIMIT = 10;
|
||||
uint32_t _requestLimit { DEFAULT_REQUEST_LIMIT };
|
||||
};
|
||||
|
||||
/// Wrapper to expose resources to JS/QML
|
||||
|
@ -200,25 +204,20 @@ public:
|
|||
|
||||
Q_INVOKABLE QVariantList getResourceList();
|
||||
|
||||
static void setRequestLimit(int limit);
|
||||
static int getRequestLimit() { return _requestLimit; }
|
||||
|
||||
static int getRequestsActive() { return _requestsActive; }
|
||||
static void setRequestLimit(uint32_t limit);
|
||||
static uint32_t getRequestLimit() { return DependencyManager::get<ResourceCacheSharedItems>()->getRequestLimit(); }
|
||||
|
||||
void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
|
||||
qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; }
|
||||
|
||||
static QList<QSharedPointer<Resource>> getLoadingRequests();
|
||||
|
||||
static int getPendingRequestCount();
|
||||
|
||||
static int getLoadingRequestCount();
|
||||
static uint32_t getPendingRequestCount();
|
||||
static uint32_t getLoadingRequestCount();
|
||||
|
||||
ResourceCache(QObject* parent = nullptr);
|
||||
virtual ~ResourceCache();
|
||||
|
||||
void refreshAll();
|
||||
void refresh(const QUrl& url);
|
||||
void clearUnusedResources();
|
||||
|
||||
signals:
|
||||
|
@ -272,11 +271,11 @@ private:
|
|||
friend class ScriptableResourceCache;
|
||||
|
||||
void reserveUnusedResource(qint64 resourceSize);
|
||||
void resetResourceCounters();
|
||||
void removeResource(const QUrl& url, qint64 size = 0);
|
||||
|
||||
static int _requestLimit;
|
||||
static int _requestsActive;
|
||||
void resetTotalResourceCounter();
|
||||
void resetUnusedResourceCounter();
|
||||
void resetResourceCounters();
|
||||
|
||||
// Resources
|
||||
QHash<QUrl, QWeakPointer<Resource>> _resources;
|
||||
|
@ -293,10 +292,6 @@ private:
|
|||
|
||||
std::atomic<size_t> _numUnusedResources { 0 };
|
||||
std::atomic<qint64> _unusedResourcesSize { 0 };
|
||||
|
||||
// Pending resources
|
||||
QQueue<QUrl> _resourcesToBeGotten;
|
||||
QReadWriteLock _resourcesToBeGottenLock { QReadWriteLock::Recursive };
|
||||
};
|
||||
|
||||
/// Wrapper to expose resource caches to JS/QML
|
||||
|
@ -455,7 +450,7 @@ protected:
|
|||
virtual void makeRequest();
|
||||
|
||||
/// Checks whether the resource is cacheable.
|
||||
virtual bool isCacheable() const { return true; }
|
||||
virtual bool isCacheable() const { return _loaded; }
|
||||
|
||||
/// Called when the download has finished.
|
||||
/// This should be overridden by subclasses that need to process the data once it is downloaded.
|
||||
|
|
|
@ -701,7 +701,7 @@ void CharacterController::updateState() {
|
|||
const btScalar GROUND_TO_FLY_THRESHOLD = 0.8f * _radius + _halfHeight;
|
||||
const quint64 TAKE_OFF_TO_IN_AIR_PERIOD = 250 * MSECS_PER_SECOND;
|
||||
const btScalar MIN_HOVER_HEIGHT = _scaleFactor * DEFAULT_AVATAR_MIN_HOVER_HEIGHT;
|
||||
const quint64 JUMP_TO_HOVER_PERIOD = 1100 * MSECS_PER_SECOND;
|
||||
const quint64 JUMP_TO_HOVER_PERIOD = _scaleFactor < 1.0f ? _scaleFactor * 1100 * MSECS_PER_SECOND : 1100 * MSECS_PER_SECOND;
|
||||
|
||||
// scan for distant floor
|
||||
// rayStart is at center of bottom sphere
|
||||
|
|
|
@ -55,85 +55,46 @@ BackgroundStage::BackgroundPointer BackgroundStage::removeBackground(Index index
|
|||
|
||||
|
||||
void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
const auto& lightingModel = inputs;
|
||||
const auto& lightingModel = inputs.get0();
|
||||
if (!lightingModel->isBackgroundEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Background rendering decision
|
||||
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
assert(backgroundStage);
|
||||
|
||||
graphics::SunSkyStagePointer background;
|
||||
const auto& backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
const auto& backgroundFrame = inputs.get1();
|
||||
graphics::SkyboxPointer skybox;
|
||||
if (backgroundStage->_currentFrame._backgrounds.size()) {
|
||||
auto backgroundId = backgroundStage->_currentFrame._backgrounds.front();
|
||||
auto background = backgroundStage->getBackground(backgroundId);
|
||||
if (backgroundStage && backgroundFrame->_backgrounds.size()) {
|
||||
const auto& background = backgroundStage->getBackground(backgroundFrame->_backgrounds.front());
|
||||
if (background) {
|
||||
skybox = background->getSkybox();
|
||||
}
|
||||
}
|
||||
/* auto backgroundMode = skyStage->getBackgroundMode();
|
||||
|
||||
switch (backgroundMode) {
|
||||
case graphics::SunSkyStage::SKY_DEFAULT: {
|
||||
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
||||
auto sceneKeyLight = scene->getKeyLight();
|
||||
|
||||
scene->setSunModelEnable(false);
|
||||
sceneKeyLight->setColor(ColorUtils::toVec3(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_COLOR));
|
||||
sceneKeyLight->setIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY);
|
||||
sceneKeyLight->setAmbientIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY);
|
||||
sceneKeyLight->setDirection(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION);
|
||||
// fall through: render a skybox (if available), or the defaults (if requested)
|
||||
}
|
||||
|
||||
case graphics::SunSkyStage::SKY_BOX: {*/
|
||||
if (skybox && !skybox->empty()) {
|
||||
PerformanceTimer perfTimer("skybox");
|
||||
auto args = renderContext->args;
|
||||
PerformanceTimer perfTimer("skybox");
|
||||
auto args = renderContext->args;
|
||||
|
||||
gpu::doInBatch("DrawBackgroundStage::run", args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
gpu::doInBatch("DrawBackgroundStage::run", args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
batch.enableSkybox(true);
|
||||
batch.enableSkybox(true);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
skybox->render(batch, args->getViewFrustum());
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
|
||||
// break;
|
||||
}
|
||||
// fall through: render defaults (if requested)
|
||||
// }
|
||||
/*
|
||||
case graphics::SunSkyStage::SKY_DEFAULT_AMBIENT_TEXTURE: {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) {
|
||||
auto scene = DependencyManager::get<SceneScriptingInterface>()->getStage();
|
||||
auto sceneKeyLight = scene->getKeyLight();
|
||||
auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture();
|
||||
if (defaultSkyboxAmbientTexture) {
|
||||
sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance());
|
||||
sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture);
|
||||
}
|
||||
// fall through: render defaults skybox
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
skybox->render(batch, args->getViewFrustum());
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
BackgroundStageSetup::BackgroundStageSetup() {
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
|
||||
BackgroundStage::BackgroundIndices _backgrounds;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
|
@ -76,18 +77,16 @@ public:
|
|||
|
||||
BackgroundStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
class DrawBackgroundStage {
|
||||
public:
|
||||
using Inputs = LightingModelPointer;
|
||||
using Inputs = render::VaryingSet2<LightingModelPointer, BackgroundStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<DrawBackgroundStage, Inputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
DrawBackgroundStage() {}
|
||||
|
||||
protected:
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,16 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
const auto frameTransform = inputs.get0();
|
||||
const auto inputFrameBuffer = inputs.get1();
|
||||
const auto bloom = inputs.get2();
|
||||
const auto bloomFrame = inputs.get2();
|
||||
const auto& bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
graphics::BloomPointer bloom;
|
||||
if (bloomStage && bloomFrame->_blooms.size()) {
|
||||
bloom = bloomStage->getBloom(bloomFrame->_blooms.front());
|
||||
}
|
||||
if (!bloom) {
|
||||
renderContext->taskFlow.abortTask();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(inputFrameBuffer->hasColor());
|
||||
|
||||
|
@ -65,11 +74,6 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y };
|
||||
|
||||
if (!bloom) {
|
||||
renderContext->taskFlow.abortTask();
|
||||
return;
|
||||
}
|
||||
|
||||
_parameters.edit()._threshold = bloom->getBloomThreshold();
|
||||
|
||||
gpu::doInBatch("BloomThreshold::run", args->_context, [&](gpu::Batch& batch) {
|
||||
|
@ -89,6 +93,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
outputs.edit0() = _outputBuffer;
|
||||
outputs.edit1() = 0.5f + bloom->getBloomSize() * 3.5f;
|
||||
outputs.edit2() = bloom;
|
||||
}
|
||||
|
||||
BloomApply::BloomApply() {
|
||||
|
@ -296,9 +301,9 @@ void BloomEffect::build(JobModel& task, const render::Varying& inputs, render::V
|
|||
const auto blurFB2 = task.addJob<render::BlurGaussian>("BloomBlur2", blurInput2);
|
||||
|
||||
const auto& frameBuffer = inputs.getN<Inputs>(1);
|
||||
const auto& bloom = inputs.getN<Inputs>(2);
|
||||
|
||||
// Mix all blur levels at quarter resolution
|
||||
const auto bloom = bloomOutputs.getN<BloomThreshold::Outputs>(2);
|
||||
const auto applyInput = BloomApply::Inputs(blurInputBuffer, blurFB0, blurFB1, blurFB2, bloom).asVarying();
|
||||
task.addJob<BloomApply>("BloomApply", applyInput);
|
||||
// And then blend result in additive manner on top of final color buffer
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <render/Engine.h>
|
||||
|
||||
#include "graphics/Bloom.h"
|
||||
#include "BloomStage.h"
|
||||
|
||||
#include "DeferredFrameTransform.h"
|
||||
|
||||
|
@ -28,8 +28,8 @@ class BloomThresholdConfig : public render::Job::Config {
|
|||
|
||||
class BloomThreshold {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, graphics::BloomPointer>;
|
||||
using Outputs = render::VaryingSet2<gpu::FramebufferPointer, float>;
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, BloomStage::FramePointer>;
|
||||
using Outputs = render::VaryingSet3<gpu::FramebufferPointer, float, graphics::BloomPointer>;
|
||||
using Config = BloomThresholdConfig;
|
||||
using JobModel = render::Job::ModelIO<BloomThreshold, Inputs, Outputs, Config>;
|
||||
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
|
||||
class BloomEffect {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, graphics::BloomPointer>;
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, BloomStage::FramePointer>;
|
||||
using Config = BloomConfig;
|
||||
using JobModel = render::Task::ModelI<BloomEffect, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -16,16 +16,6 @@
|
|||
std::string BloomStage::_stageName { "BLOOM_STAGE"};
|
||||
const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
FetchBloomStage::FetchBloomStage() {
|
||||
_bloom = std::make_shared<graphics::Bloom>();
|
||||
}
|
||||
|
||||
void FetchBloomStage::configure(const Config& config) {
|
||||
_bloom->setBloomIntensity(config.bloomIntensity);
|
||||
_bloom->setBloomThreshold(config.bloomThreshold);
|
||||
_bloom->setBloomSize(config.bloomSize);
|
||||
}
|
||||
|
||||
BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const {
|
||||
auto found = _bloomMap.find(bloom);
|
||||
if (found != _bloomMap.end()) {
|
||||
|
@ -66,14 +56,3 @@ void BloomStageSetup::run(const render::RenderContextPointer& renderContext) {
|
|||
renderContext->_scene->resetStage(BloomStage::getName(), std::make_shared<BloomStage>());
|
||||
}
|
||||
}
|
||||
|
||||
void FetchBloomStage::run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom) {
|
||||
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
|
||||
bloom = nullptr;
|
||||
if (bloomStage->_currentFrame._blooms.size() != 0) {
|
||||
auto bloomId = bloomStage->_currentFrame._blooms.front();
|
||||
bloom = bloomStage->getBloom(bloomId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
|
||||
BloomStage::BloomIndices _blooms;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
|
@ -102,17 +103,4 @@ signals:
|
|||
void dirty();
|
||||
};
|
||||
|
||||
class FetchBloomStage {
|
||||
public:
|
||||
using Config = FetchBloomConfig;
|
||||
using JobModel = render::Job::ModelO<FetchBloomStage, graphics::BloomPointer, Config>;
|
||||
|
||||
FetchBloomStage();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom);
|
||||
|
||||
private:
|
||||
graphics::BloomPointer _bloom;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -405,6 +405,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
|
|||
auto& ambientOcclusionFramebuffer = inputs.get3();
|
||||
auto& velocityFramebuffer = inputs.get4();
|
||||
auto& frameTransform = inputs.get5();
|
||||
auto& lightFrame = inputs.get6();
|
||||
|
||||
gpu::doInBatch("DebugDeferredBuffer::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
@ -443,7 +444,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
|
|||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
assert(lightStage->getNumLights() > 0);
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(*lightFrame);
|
||||
const auto& globalShadow = lightAndShadow.second;
|
||||
if (globalShadow) {
|
||||
batch.setResourceTexture(Textures::Shadow, globalShadow->map);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "AmbientOcclusionEffect.h"
|
||||
#include "VelocityBufferPass.h"
|
||||
|
||||
#include "LightStage.h"
|
||||
|
||||
class DebugDeferredBufferConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool enabled MEMBER enabled)
|
||||
|
@ -39,12 +41,13 @@ signals:
|
|||
|
||||
class DebugDeferredBuffer {
|
||||
public:
|
||||
using Inputs = render::VaryingSet6<DeferredFramebufferPointer,
|
||||
using Inputs = render::VaryingSet7<DeferredFramebufferPointer,
|
||||
LinearDepthFramebufferPointer,
|
||||
SurfaceGeometryFramebufferPointer,
|
||||
AmbientOcclusionFramebufferPointer,
|
||||
VelocityFramebufferPointer,
|
||||
DeferredFrameTransformPointer>;
|
||||
DeferredFrameTransformPointer,
|
||||
LightStage::FramePointer>;
|
||||
using Config = DebugDeferredBufferConfig;
|
||||
using JobModel = render::Job::ModelI<DebugDeferredBuffer, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -70,17 +70,22 @@ void DeferredLightingEffect::init() {
|
|||
loadLightProgram(shader::render_utils::program::local_lights_drawOutline, true, _localLightOutline, _localLightOutlineLocations);
|
||||
}
|
||||
|
||||
// FIXME: figure out how to move lightFrame into a varying in GeometryCache and RenderPipelines
|
||||
void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch) {
|
||||
setupKeyLightBatch(args, batch, args->_scene->getStage<LightStage>()->_currentFrame);
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, const LightStage::Frame& lightFrame) {
|
||||
PerformanceTimer perfTimer("DLE->setupBatch()");
|
||||
graphics::LightPointer keySunLight;
|
||||
auto lightStage = args->_scene->getStage<LightStage>();
|
||||
if (lightStage) {
|
||||
keySunLight = lightStage->getCurrentKeyLight();
|
||||
keySunLight = lightStage->getCurrentKeyLight(lightFrame);
|
||||
}
|
||||
|
||||
graphics::LightPointer keyAmbiLight;
|
||||
if (lightStage) {
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight();
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight(lightFrame);
|
||||
}
|
||||
|
||||
if (keySunLight) {
|
||||
|
@ -361,12 +366,6 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input
|
|||
// For the rest of the rendering, bind the lighting model
|
||||
batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer());
|
||||
});
|
||||
|
||||
|
||||
// Prepare a fresh Light Frame
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
lightStage->_currentFrame.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -374,7 +373,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
const DeferredFrameTransformPointer& frameTransform,
|
||||
const DeferredFramebufferPointer& deferredFramebuffer,
|
||||
const LightingModelPointer& lightingModel,
|
||||
const graphics::HazePointer& haze,
|
||||
const LightStage::FramePointer& lightFrame,
|
||||
const HazeStage::FramePointer& hazeFrame,
|
||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||
|
@ -434,7 +434,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
assert(lightStage->getNumLights() > 0);
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
|
||||
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(*lightFrame);
|
||||
const auto& globalShadow = lightAndShadow.second;
|
||||
|
||||
// Bind the shadow buffers
|
||||
|
@ -448,8 +448,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
auto keyLight = lightAndShadow.first;
|
||||
|
||||
graphics::LightPointer ambientLight;
|
||||
if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
|
||||
ambientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front());
|
||||
if (lightStage && lightFrame->_ambientLights.size()) {
|
||||
ambientLight = lightStage->getLight(lightFrame->_ambientLights.front());
|
||||
}
|
||||
bool hasAmbientMap = (ambientLight != nullptr);
|
||||
|
||||
|
@ -458,8 +458,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
// Check if keylight casts shadows
|
||||
bool keyLightCastShadows { false };
|
||||
|
||||
if (renderShadows && lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||
graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
|
||||
if (renderShadows && lightStage && lightFrame->_sunLights.size()) {
|
||||
graphics::LightPointer keyLight = lightStage->getLight(lightFrame->_sunLights.front());
|
||||
if (keyLight) {
|
||||
keyLightCastShadows = keyLight->getCastShadows();
|
||||
}
|
||||
|
@ -496,13 +496,17 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
}
|
||||
|
||||
// Setup the global lighting
|
||||
deferredLightingEffect->setupKeyLightBatch(args, batch);
|
||||
deferredLightingEffect->setupKeyLightBatch(args, batch, *lightFrame);
|
||||
|
||||
// Haze
|
||||
if (haze) {
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer());
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
deferredLightingEffect->unsetKeyLightBatch(batch);
|
||||
|
@ -617,7 +621,8 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
|
|||
auto lightClusters = inputs.get6();
|
||||
auto args = renderContext->args;
|
||||
|
||||
const auto haze = inputs.get7();
|
||||
const auto& lightFrame = inputs.get7();
|
||||
const auto& hazeFrame = inputs.get8();
|
||||
|
||||
if (!_gpuTimer) {
|
||||
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
|
||||
|
@ -626,10 +631,10 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
|
|||
auto previousBatch = args->_batch;
|
||||
gpu::doInBatch(nullptr, args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
_gpuTimer->begin(batch);
|
||||
_gpuTimer->begin(batch);
|
||||
|
||||
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, lightFrame, hazeFrame, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource, _renderShadows);
|
||||
|
||||
setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, haze, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource, _renderShadows);
|
||||
|
||||
lightsJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters);
|
||||
|
||||
cleanupJob.run(renderContext);
|
||||
|
@ -647,19 +652,18 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs
|
|||
void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
|
||||
|
||||
if (!_defaultLight || !_defaultBackground) {
|
||||
if (!_defaultSkyboxTexture) {
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
{
|
||||
PROFILE_RANGE(render, "Process Default Skybox");
|
||||
QFileSelector fileSelector;
|
||||
fileSelector.setExtraSelectors(FileUtils::getFileSelectors());
|
||||
auto skyboxUrl = fileSelector.select(PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.ktx");
|
||||
if (!_defaultSkyboxNetworkTexture) {
|
||||
PROFILE_RANGE(render, "Process Default Skybox");
|
||||
_defaultSkyboxNetworkTexture = DependencyManager::get<TextureCache>()->getTexture(
|
||||
PathUtils::resourcesUrl() + "images/Default-Sky-9-cubemap/Default-Sky-9-cubemap.texmeta.json", image::TextureUsage::CUBE_TEXTURE);
|
||||
}
|
||||
|
||||
_defaultSkyboxTexture = gpu::Texture::unserialize(skyboxUrl.toStdString());
|
||||
_defaultSkyboxAmbientTexture = _defaultSkyboxTexture;
|
||||
|
||||
_defaultSkybox->setCubemap(_defaultSkyboxTexture);
|
||||
}
|
||||
if (_defaultSkyboxNetworkTexture && _defaultSkyboxNetworkTexture->isLoaded() && _defaultSkyboxNetworkTexture->getGPUTexture()) {
|
||||
_defaultSkyboxAmbientTexture = _defaultSkyboxNetworkTexture->getGPUTexture();
|
||||
_defaultSkybox->setCubemap(_defaultSkyboxAmbientTexture);
|
||||
} else {
|
||||
// Don't do anything until the skybox has loaded
|
||||
return;
|
||||
}
|
||||
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
void init();
|
||||
|
||||
static void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch);
|
||||
static void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, const LightStage::Frame& lightFrame);
|
||||
static void unsetKeyLightBatch(gpu::Batch& batch);
|
||||
|
||||
static void setupLocalLightsBatch(gpu::Batch& batch, const LightClustersPointer& lightClusters);
|
||||
|
@ -139,13 +140,13 @@ public:
|
|||
|
||||
class RenderDeferredSetup {
|
||||
public:
|
||||
// using JobModel = render::Job::ModelI<RenderDeferredSetup, DeferredFrameTransformPointer>;
|
||||
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext,
|
||||
const DeferredFrameTransformPointer& frameTransform,
|
||||
const DeferredFramebufferPointer& deferredFramebuffer,
|
||||
const LightingModelPointer& lightingModel,
|
||||
const graphics::HazePointer& haze,
|
||||
const LightStage::FramePointer& lightFrame,
|
||||
const HazeStage::FramePointer& hazeFrame,
|
||||
const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer,
|
||||
const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer,
|
||||
const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource,
|
||||
|
@ -181,9 +182,9 @@ using RenderDeferredConfig = render::GPUJobConfig;
|
|||
|
||||
class RenderDeferred {
|
||||
public:
|
||||
using Inputs = render::VaryingSet8 <
|
||||
using Inputs = render::VaryingSet9<
|
||||
DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer,
|
||||
AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer, LightClustersPointer, graphics::HazePointer>;
|
||||
AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer, LightClustersPointer, LightStage::FramePointer, HazeStage::FramePointer>;
|
||||
|
||||
using Config = RenderDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||
|
@ -220,7 +221,7 @@ protected:
|
|||
graphics::HazePointer _defaultHaze{ nullptr };
|
||||
HazeStage::Index _defaultHazeID{ HazeStage::INVALID_INDEX };
|
||||
graphics::SkyboxPointer _defaultSkybox { new ProceduralSkybox() };
|
||||
gpu::TexturePointer _defaultSkyboxTexture;
|
||||
NetworkTexturePointer _defaultSkyboxNetworkTexture;
|
||||
gpu::TexturePointer _defaultSkyboxAmbientTexture;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "StencilMaskPass.h"
|
||||
#include "FramebufferCache.h"
|
||||
#include "HazeStage.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
namespace ru {
|
||||
|
@ -32,98 +31,15 @@ namespace gr {
|
|||
using graphics::slot::buffer::Buffer;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeColor(const glm::vec3 value) {
|
||||
hazeColor = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeGlareAngle(const float value) {
|
||||
hazeGlareAngle = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeGlareColor(const glm::vec3 value) {
|
||||
hazeGlareColor = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeBaseReference(const float value) {
|
||||
hazeBaseReference = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeActive(const bool active) {
|
||||
isHazeActive = active;
|
||||
}
|
||||
|
||||
void HazeConfig::setAltitudeBased(const bool active) {
|
||||
isAltitudeBased = active;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeAttenuateKeyLight(const bool active) {
|
||||
isHazeAttenuateKeyLight = active;
|
||||
}
|
||||
|
||||
void HazeConfig::setModulateColorActive(const bool active) {
|
||||
isModulateColorActive = active;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeEnableGlare(const bool active) {
|
||||
isHazeEnableGlare = active;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeRange(const float value) {
|
||||
hazeRange = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeAltitude(const float value) {
|
||||
hazeHeight = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeKeyLightRange(const float value) {
|
||||
hazeKeyLightRange = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeKeyLightAltitude(const float value) {
|
||||
hazeKeyLightAltitude = value;
|
||||
}
|
||||
|
||||
void HazeConfig::setHazeBackgroundBlend(const float value) {
|
||||
hazeBackgroundBlend = value;
|
||||
}
|
||||
|
||||
MakeHaze::MakeHaze() {
|
||||
_haze = std::make_shared<graphics::Haze>();
|
||||
}
|
||||
|
||||
void MakeHaze::configure(const Config& config) {
|
||||
_haze->setHazeColor(config.hazeColor);
|
||||
_haze->setHazeGlareBlend(graphics::Haze::convertGlareAngleToPower(config.hazeGlareAngle));
|
||||
|
||||
_haze->setHazeGlareColor(config.hazeGlareColor);
|
||||
_haze->setHazeBaseReference(config.hazeBaseReference);
|
||||
|
||||
_haze->setHazeActive(config.isHazeActive);
|
||||
_haze->setAltitudeBased(config.isAltitudeBased);
|
||||
_haze->setHazeAttenuateKeyLight(config.isHazeAttenuateKeyLight);
|
||||
_haze->setModulateColorActive(config.isModulateColorActive);
|
||||
_haze->setHazeEnableGlare(config.isHazeEnableGlare);
|
||||
|
||||
_haze->setHazeRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange));
|
||||
_haze->setHazeAltitudeFactor(graphics::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight));
|
||||
|
||||
_haze->setHazeKeyLightRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange));
|
||||
_haze->setHazeKeyLightAltitudeFactor(graphics::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude));
|
||||
|
||||
_haze->setHazeBackgroundBlend(config.hazeBackgroundBlend);
|
||||
}
|
||||
|
||||
void MakeHaze::run(const render::RenderContextPointer& renderContext, graphics::HazePointer& haze) {
|
||||
haze = _haze;
|
||||
}
|
||||
|
||||
void DrawHaze::configure(const Config& config) {
|
||||
}
|
||||
|
||||
void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
const auto haze = inputs.get0();
|
||||
if (haze == nullptr) {
|
||||
const auto hazeFrame = inputs.get0();
|
||||
const auto& hazeStage = renderContext->args->_scene->getStage<HazeStage>();
|
||||
graphics::HazePointer haze;
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
haze = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
}
|
||||
|
||||
if (!haze) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -131,6 +47,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
const auto framebuffer = inputs.get2();
|
||||
const auto transformBuffer = inputs.get3();
|
||||
const auto lightingModel = inputs.get4();
|
||||
const auto lightFrame = inputs.get5();
|
||||
|
||||
auto depthBuffer = framebuffer->getLinearDepthTexture();
|
||||
|
||||
|
@ -161,17 +78,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport));
|
||||
|
||||
batch.setPipeline(_hazePipeline);
|
||||
|
||||
auto hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) {
|
||||
graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
} else {
|
||||
// Something is wrong, so just quit Haze
|
||||
return;
|
||||
}
|
||||
}
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, haze->getHazeParametersBuffer());
|
||||
|
||||
batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer());
|
||||
batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer());
|
||||
|
@ -179,13 +86,12 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
|
|||
auto lightStage = args->_scene->getStage<LightStage>();
|
||||
if (lightStage) {
|
||||
graphics::LightPointer keyLight;
|
||||
keyLight = lightStage->getCurrentKeyLight();
|
||||
keyLight = lightStage->getCurrentKeyLight(*lightFrame);
|
||||
if (keyLight) {
|
||||
batch.setUniformBuffer(gr::Buffer::KeyLight, keyLight->getLightSchemaBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,152 +19,20 @@
|
|||
#include <gpu/Pipeline.h>
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/Haze.h>
|
||||
|
||||
#include "SurfaceGeometryPass.h"
|
||||
#include "LightingModel.h"
|
||||
|
||||
#include "HazeStage.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
using LinearDepthFramebufferPointer = std::shared_ptr<LinearDepthFramebuffer>;
|
||||
|
||||
class MakeHazeConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty);
|
||||
Q_PROPERTY(float hazeGlareAngle MEMBER hazeGlareAngle WRITE setHazeGlareAngle NOTIFY dirty);
|
||||
|
||||
Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty);
|
||||
Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty);
|
||||
|
||||
Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty);
|
||||
Q_PROPERTY(bool isAltitudeBased MEMBER isAltitudeBased WRITE setAltitudeBased NOTIFY dirty);
|
||||
Q_PROPERTY(bool isHazeAttenuateKeyLight MEMBER isHazeAttenuateKeyLight WRITE setHazeAttenuateKeyLight NOTIFY dirty);
|
||||
Q_PROPERTY(bool isModulateColorActive MEMBER isModulateColorActive WRITE setModulateColorActive NOTIFY dirty);
|
||||
Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty);
|
||||
|
||||
Q_PROPERTY(float hazeRange MEMBER hazeRange WRITE setHazeRange NOTIFY dirty);
|
||||
Q_PROPERTY(float hazeHeight MEMBER hazeHeight WRITE setHazeAltitude NOTIFY dirty);
|
||||
|
||||
Q_PROPERTY(float hazeKeyLightRange MEMBER hazeKeyLightRange WRITE setHazeKeyLightRange NOTIFY dirty);
|
||||
Q_PROPERTY(float hazeKeyLightAltitude MEMBER hazeKeyLightAltitude WRITE setHazeKeyLightAltitude NOTIFY dirty);
|
||||
|
||||
Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty);
|
||||
|
||||
public:
|
||||
MakeHazeConfig() : render::Job::Config() {}
|
||||
|
||||
glm::vec3 hazeColor{ graphics::Haze::INITIAL_HAZE_COLOR };
|
||||
float hazeGlareAngle{ graphics::Haze::INITIAL_HAZE_GLARE_ANGLE };
|
||||
|
||||
glm::vec3 hazeGlareColor{ graphics::Haze::INITIAL_HAZE_GLARE_COLOR };
|
||||
float hazeBaseReference{ graphics::Haze::INITIAL_HAZE_BASE_REFERENCE };
|
||||
|
||||
bool isHazeActive{ false };
|
||||
bool isAltitudeBased{ false };
|
||||
bool isHazeAttenuateKeyLight{ false };
|
||||
bool isModulateColorActive{ false };
|
||||
bool isHazeEnableGlare{ false };
|
||||
|
||||
float hazeRange{ graphics::Haze::INITIAL_HAZE_RANGE };
|
||||
float hazeHeight{ graphics::Haze::INITIAL_HAZE_HEIGHT };
|
||||
|
||||
float hazeKeyLightRange{ graphics::Haze::INITIAL_KEY_LIGHT_RANGE };
|
||||
float hazeKeyLightAltitude{ graphics::Haze::INITIAL_KEY_LIGHT_ALTITUDE };
|
||||
|
||||
float hazeBackgroundBlend{ graphics::Haze::INITIAL_HAZE_BACKGROUND_BLEND };
|
||||
|
||||
public slots:
|
||||
void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); }
|
||||
void setHazeGlareAngle(const float value) { hazeGlareAngle = value; emit dirty(); }
|
||||
|
||||
void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); }
|
||||
void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); }
|
||||
|
||||
void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); }
|
||||
void setAltitudeBased(const bool active) { isAltitudeBased = active; emit dirty(); }
|
||||
void setHazeAttenuateKeyLight(const bool active) { isHazeAttenuateKeyLight = active; emit dirty(); }
|
||||
void setModulateColorActive(const bool active) { isModulateColorActive = active; emit dirty(); }
|
||||
void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); }
|
||||
|
||||
void setHazeRange(const float value) { hazeRange = value; emit dirty(); }
|
||||
void setHazeAltitude(const float value) { hazeHeight = value; emit dirty(); }
|
||||
|
||||
void setHazeKeyLightRange(const float value) { hazeKeyLightRange = value; emit dirty(); }
|
||||
void setHazeKeyLightAltitude(const float value) { hazeKeyLightAltitude = value; emit dirty(); }
|
||||
|
||||
void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); }
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class MakeHaze {
|
||||
public:
|
||||
using Config = MakeHazeConfig;
|
||||
using JobModel = render::Job::ModelO<MakeHaze, graphics::HazePointer, Config>;
|
||||
|
||||
MakeHaze();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, graphics::HazePointer& haze);
|
||||
|
||||
private:
|
||||
graphics::HazePointer _haze;
|
||||
};
|
||||
|
||||
class HazeConfig : public render::Job::Config {
|
||||
public:
|
||||
HazeConfig() : render::Job::Config(true) {}
|
||||
|
||||
// attributes
|
||||
glm::vec3 hazeColor{ graphics::Haze::INITIAL_HAZE_COLOR };
|
||||
float hazeGlareAngle{ graphics::Haze::INITIAL_HAZE_GLARE_ANGLE };
|
||||
|
||||
glm::vec3 hazeGlareColor{ graphics::Haze::INITIAL_HAZE_GLARE_COLOR };
|
||||
float hazeBaseReference{ graphics::Haze::INITIAL_HAZE_BASE_REFERENCE };
|
||||
|
||||
bool isHazeActive{ false }; // Setting this to true will set haze to on
|
||||
bool isAltitudeBased{ false };
|
||||
bool isHazeAttenuateKeyLight{ false };
|
||||
bool isModulateColorActive{ false };
|
||||
bool isHazeEnableGlare{ false };
|
||||
|
||||
float hazeRange{ graphics::Haze::INITIAL_HAZE_RANGE };
|
||||
float hazeHeight{ graphics::Haze::INITIAL_HAZE_HEIGHT };
|
||||
|
||||
float hazeKeyLightRange{ graphics::Haze::INITIAL_KEY_LIGHT_RANGE };
|
||||
float hazeKeyLightAltitude{ graphics::Haze::INITIAL_KEY_LIGHT_ALTITUDE };
|
||||
|
||||
float hazeBackgroundBlend{ graphics::Haze::INITIAL_HAZE_BACKGROUND_BLEND };
|
||||
|
||||
// methods
|
||||
void setHazeColor(const glm::vec3 value);
|
||||
void setHazeGlareAngle(const float value);
|
||||
|
||||
void setHazeGlareColor(const glm::vec3 value);
|
||||
void setHazeBaseReference(const float value);
|
||||
|
||||
void setHazeActive(const bool active);
|
||||
void setAltitudeBased(const bool active);
|
||||
void setHazeAttenuateKeyLight(const bool active);
|
||||
void setModulateColorActive(const bool active);
|
||||
void setHazeEnableGlare(const bool active);
|
||||
|
||||
void setHazeRange(const float value);
|
||||
void setHazeAltitude(const float value);
|
||||
|
||||
void setHazeKeyLightRange(const float value);
|
||||
void setHazeKeyLightAltitude(const float value);
|
||||
|
||||
void setHazeBackgroundBlend(const float value);
|
||||
};
|
||||
|
||||
class DrawHaze {
|
||||
public:
|
||||
using Inputs = render::VaryingSet5<graphics::HazePointer, gpu::FramebufferPointer, LinearDepthFramebufferPointer, DeferredFrameTransformPointer, LightingModelPointer>;
|
||||
using Config = HazeConfig;
|
||||
using JobModel = render::Job::ModelI<DrawHaze, Inputs, Config>;
|
||||
using Inputs = render::VaryingSet6<HazeStage::FramePointer, gpu::FramebufferPointer, LinearDepthFramebufferPointer, DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<DrawHaze, Inputs>;
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,32 +16,6 @@
|
|||
std::string HazeStage::_stageName { "HAZE_STAGE"};
|
||||
const HazeStage::Index HazeStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
FetchHazeStage::FetchHazeStage() {
|
||||
_haze = std::make_shared<graphics::Haze>();
|
||||
}
|
||||
|
||||
void FetchHazeStage::configure(const Config& config) {
|
||||
_haze->setHazeColor(config.hazeColor);
|
||||
_haze->setHazeGlareBlend(graphics::Haze::convertGlareAngleToPower(config.hazeGlareAngle));
|
||||
|
||||
_haze->setHazeGlareColor(config.hazeGlareColor);
|
||||
_haze->setHazeBaseReference(config.hazeBaseReference);
|
||||
|
||||
_haze->setHazeActive(config.isHazeActive);
|
||||
_haze->setAltitudeBased(config.isAltitudeBased);
|
||||
_haze->setHazeAttenuateKeyLight(config.isHazeAttenuateKeyLight);
|
||||
_haze->setModulateColorActive(config.isModulateColorActive);
|
||||
_haze->setHazeEnableGlare(config.isHazeEnableGlare);
|
||||
|
||||
_haze->setHazeRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange));
|
||||
_haze->setHazeAltitudeFactor(graphics::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight));
|
||||
|
||||
_haze->setHazeKeyLightRangeFactor(graphics::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange));
|
||||
_haze->setHazeKeyLightAltitudeFactor(graphics::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude));
|
||||
|
||||
_haze->setHazeBackgroundBlend(config.hazeBackgroundBlend);
|
||||
}
|
||||
|
||||
HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const {
|
||||
auto found = _hazeMap.find(haze);
|
||||
if (found != _hazeMap.end()) {
|
||||
|
@ -84,15 +58,4 @@ void HazeStageSetup::run(const render::RenderContextPointer& renderContext) {
|
|||
if (!stage) {
|
||||
renderContext->_scene->resetStage(HazeStage::getName(), std::make_shared<HazeStage>());
|
||||
}
|
||||
}
|
||||
|
||||
void FetchHazeStage::run(const render::RenderContextPointer& renderContext, graphics::HazePointer& haze) {
|
||||
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
|
||||
assert(hazeStage);
|
||||
|
||||
haze = nullptr;
|
||||
if (hazeStage->_currentFrame._hazes.size() != 0) {
|
||||
auto hazeId = hazeStage->_currentFrame._hazes.front();
|
||||
haze = hazeStage->getHaze(hazeId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,6 +65,7 @@ public:
|
|||
|
||||
HazeStage::HazeIndices _hazes;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
|
@ -150,18 +151,4 @@ public slots:
|
|||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class FetchHazeStage {
|
||||
public:
|
||||
using Config = FetchHazeConfig;
|
||||
using JobModel = render::Job::ModelO<FetchHazeStage, graphics::HazePointer, Config>;
|
||||
|
||||
FetchHazeStage();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, graphics::HazePointer& haze);
|
||||
|
||||
private:
|
||||
graphics::HazePointer _haze;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -175,15 +175,15 @@ void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
|
|||
|
||||
}
|
||||
|
||||
void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) {
|
||||
void LightClusters::updateLightFrame(const LightStage::FramePointer& lightFrame, bool points, bool spots) {
|
||||
|
||||
// start fresh
|
||||
_visibleLightIndices.clear();
|
||||
|
||||
// Now gather the lights
|
||||
// gather lights
|
||||
auto& srcPointLights = lightFrame._pointLights;
|
||||
auto& srcSpotLights = lightFrame._spotLights;
|
||||
auto& srcPointLights = lightFrame->_pointLights;
|
||||
auto& srcSpotLights = lightFrame->_spotLights;
|
||||
int numPointLights = (int)srcPointLights.size();
|
||||
int numSpotLights = (int)srcSpotLights.size();
|
||||
|
||||
|
@ -548,7 +548,8 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext,
|
|||
|
||||
auto deferredTransform = inputs.get0();
|
||||
auto lightingModel = inputs.get1();
|
||||
auto surfaceGeometryFramebuffer = inputs.get2();
|
||||
auto lightFrame = inputs.get2();
|
||||
auto surfaceGeometryFramebuffer = inputs.get3();
|
||||
|
||||
// first update the Grid with the new frustum
|
||||
if (!_freeze) {
|
||||
|
@ -559,7 +560,7 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext,
|
|||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
_lightClusters->updateLightStage(lightStage);
|
||||
_lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
|
||||
_lightClusters->updateLightFrame(lightFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
|
||||
|
||||
auto clusteringStats = _lightClusters->updateClusters();
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
void updateLightStage(const LightStagePointer& lightStage);
|
||||
|
||||
void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true);
|
||||
void updateLightFrame(const LightStage::FramePointer& lightFrame, bool points = true, bool spots = true);
|
||||
|
||||
glm::ivec3 updateClusters();
|
||||
|
||||
|
@ -167,7 +167,7 @@ protected:
|
|||
|
||||
class LightClusteringPass {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, LightingModelPointer, LinearDepthFramebufferPointer>;
|
||||
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer, LinearDepthFramebufferPointer>;
|
||||
using Outputs = LightClustersPointer;
|
||||
using Config = LightClusteringPassConfig;
|
||||
using JobModel = render::Job::ModelIO<LightClusteringPass, Inputs, Outputs, Config>;
|
||||
|
|
|
@ -372,36 +372,36 @@ LightStage::LightPointer LightStage::removeLight(Index index) {
|
|||
return removedLight;
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::getCurrentKeyLight() const {
|
||||
Index keyLightId{ _defaultLightId };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
LightStage::LightPointer LightStage::getCurrentKeyLight(const LightStage::Frame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!frame._sunLights.empty()) {
|
||||
keyLightId = frame._sunLights.front();
|
||||
}
|
||||
return _lights.get(keyLightId);
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::getCurrentAmbientLight() const {
|
||||
LightStage::LightPointer LightStage::getCurrentAmbientLight(const LightStage::Frame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!_currentFrame._ambientLights.empty()) {
|
||||
keyLightId = _currentFrame._ambientLights.front();
|
||||
if (!frame._ambientLights.empty()) {
|
||||
keyLightId = frame._ambientLights.front();
|
||||
}
|
||||
return _lights.get(keyLightId);
|
||||
}
|
||||
|
||||
LightStage::ShadowPointer LightStage::getCurrentKeyShadow() const {
|
||||
LightStage::ShadowPointer LightStage::getCurrentKeyShadow(const LightStage::Frame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
if (!frame._sunLights.empty()) {
|
||||
keyLightId = frame._sunLights.front();
|
||||
}
|
||||
auto shadow = getShadow(keyLightId);
|
||||
assert(shadow == nullptr || shadow->getLight() == getLight(keyLightId));
|
||||
return shadow;
|
||||
}
|
||||
|
||||
LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const {
|
||||
LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow(const LightStage::Frame& frame) const {
|
||||
Index keyLightId { _defaultLightId };
|
||||
if (!_currentFrame._sunLights.empty()) {
|
||||
keyLightId = _currentFrame._sunLights.front();
|
||||
if (!frame._sunLights.empty()) {
|
||||
keyLightId = frame._sunLights.front();
|
||||
}
|
||||
auto shadow = getShadow(keyLightId);
|
||||
auto light = getLight(keyLightId);
|
||||
|
|
|
@ -151,11 +151,6 @@ public:
|
|||
return LightAndShadow(light, shadow);
|
||||
}
|
||||
|
||||
LightPointer getCurrentKeyLight() const;
|
||||
LightPointer getCurrentAmbientLight() const;
|
||||
ShadowPointer getCurrentKeyShadow() const;
|
||||
LightAndShadow getCurrentKeyLightAndShadow() const;
|
||||
|
||||
LightStage();
|
||||
|
||||
gpu::BufferPointer getLightArrayBuffer() const { return _lightArrayBuffer; }
|
||||
|
@ -185,6 +180,7 @@ public:
|
|||
LightStage::LightIndices _sunLights;
|
||||
LightStage::LightIndices _ambientLights;
|
||||
};
|
||||
using FramePointer = std::shared_ptr<Frame>;
|
||||
|
||||
Frame _currentFrame;
|
||||
|
||||
|
@ -193,6 +189,11 @@ public:
|
|||
Index getSpotOffLight() { return _spotOffLightId; }
|
||||
Index getSunOffLight() { return _sunOffLightId; }
|
||||
|
||||
LightPointer getCurrentKeyLight(const LightStage::Frame& frame) const;
|
||||
LightPointer getCurrentAmbientLight(const LightStage::Frame& frame) const;
|
||||
ShadowPointer getCurrentKeyShadow(const LightStage::Frame& frame) const;
|
||||
LightAndShadow getCurrentKeyLightAndShadow(const LightStage::Frame& frame) const;
|
||||
|
||||
protected:
|
||||
|
||||
struct Desc {
|
||||
|
|
|
@ -197,12 +197,14 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
|
|||
});
|
||||
}
|
||||
|
||||
void ExtractFrustums::run(const render::RenderContextPointer& renderContext, Output& output) {
|
||||
void ExtractFrustums::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
const auto& lightFrame = inputs;
|
||||
|
||||
// Return view frustum
|
||||
auto& viewFrustum = output[VIEW_FRUSTUM].edit<ViewFrustumPointer>();
|
||||
if (!viewFrustum) {
|
||||
|
@ -216,7 +218,7 @@ void ExtractFrustums::run(const render::RenderContextPointer& renderContext, Out
|
|||
for (auto i = 0; i < SHADOW_CASCADE_FRUSTUM_COUNT; i++) {
|
||||
auto& shadowFrustum = output[SHADOW_CASCADE0_FRUSTUM+i].edit<ViewFrustumPointer>();
|
||||
if (lightStage) {
|
||||
auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
auto globalShadow = lightStage->getCurrentKeyShadow(*lightFrame);
|
||||
|
||||
if (globalShadow && i<(int)globalShadow->getCascadeCount()) {
|
||||
auto& cascade = globalShadow->getCascade(i);
|
||||
|
@ -229,3 +231,21 @@ void ExtractFrustums::run(const render::RenderContextPointer& renderContext, Out
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FetchCurrentFrames::run(const render::RenderContextPointer& renderContext, Outputs& outputs) {
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
outputs.edit0() = std::make_shared<LightStage::Frame>(lightStage->_currentFrame);
|
||||
|
||||
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
assert(backgroundStage);
|
||||
outputs.edit1() = std::make_shared<BackgroundStage::Frame>(backgroundStage->_currentFrame);
|
||||
|
||||
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
|
||||
assert(hazeStage);
|
||||
outputs.edit2() = std::make_shared<HazeStage::Frame>(hazeStage->_currentFrame);
|
||||
|
||||
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
outputs.edit3() = std::make_shared<BloomStage::Frame>(bloomStage->_currentFrame);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include "LightingModel.h"
|
||||
|
||||
#include "LightStage.h"
|
||||
#include "BackgroundStage.h"
|
||||
#include "HazeStage.h"
|
||||
#include "BloomStage.h"
|
||||
|
||||
class BeginGPURangeTimer {
|
||||
public:
|
||||
using JobModel = render::Job::ModelO<BeginGPURangeTimer, gpu::RangeTimerPointer>;
|
||||
|
@ -106,10 +111,22 @@ public:
|
|||
FRUSTUM_COUNT
|
||||
};
|
||||
|
||||
using Output = render::VaryingArray<ViewFrustumPointer, FRUSTUM_COUNT>;
|
||||
using JobModel = render::Job::ModelO<ExtractFrustums, Output>;
|
||||
using Inputs = LightStage::FramePointer;
|
||||
using Outputs = render::VaryingArray<ViewFrustumPointer, FRUSTUM_COUNT>;
|
||||
using JobModel = render::Job::ModelIO<ExtractFrustums, Inputs, Outputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, Output& output);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
};
|
||||
|
||||
|
||||
class FetchCurrentFrames {
|
||||
public:
|
||||
using Outputs = render::VaryingSet4<LightStage::FramePointer, BackgroundStage::FramePointer, HazeStage::FramePointer, BloomStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelO<FetchCurrentFrames, Outputs>;
|
||||
|
||||
FetchCurrentFrames() {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, Outputs& outputs);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderDeferredTask_h
|
||||
|
|
|
@ -180,29 +180,32 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now.
|
||||
task.addJob<DrawLight>("DrawLight", lights);
|
||||
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
const auto backgroundFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(1);
|
||||
const auto hazeFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(2);
|
||||
const auto bloomFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(3);
|
||||
|
||||
// Light Clustering
|
||||
// Create the cluster grid of lights, cpu job for now
|
||||
const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).asVarying();
|
||||
const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, lightFrame, linearDepthTarget).asVarying();
|
||||
const auto lightClusters = task.addJob<LightClusteringPass>("LightClustering", lightClusteringPassInputs);
|
||||
|
||||
// Add haze model
|
||||
const auto hazeModel = task.addJob<FetchHazeStage>("HazeModel");
|
||||
|
||||
// DeferredBuffer is complete, now let's shade it into the LightingBuffer
|
||||
const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, hazeModel).asVarying();
|
||||
|
||||
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, lightFrame, hazeFrame).asVarying();
|
||||
task.addJob<RenderDeferred>("RenderDeferred", deferredLightingInputs, renderShadows);
|
||||
|
||||
|
||||
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
|
||||
task.addJob<DrawBackgroundStage>("DrawBackgroundDeferred", lightingModel);
|
||||
const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying();
|
||||
task.addJob<DrawBackgroundStage>("DrawBackgroundDeferred", backgroundInputs);
|
||||
|
||||
const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel));
|
||||
const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeFrame, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel, lightFrame));
|
||||
task.addJob<DrawHaze>("DrawHazeDeferred", drawHazeInputs);
|
||||
|
||||
// Render transparent objects forward in LightingBuffer
|
||||
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel, lightClusters, jitter).asVarying();
|
||||
const auto transparentsInputs = DrawDeferred::Inputs(transparents, hazeFrame, lightFrame, lightingModel, lightClusters, jitter).asVarying();
|
||||
task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
|
||||
|
||||
// Light Cluster Grid Debuging job
|
||||
|
@ -246,8 +249,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
|
||||
|
||||
// Add bloom
|
||||
const auto bloomModel = task.addJob<FetchBloomStage>("BloomModel");
|
||||
const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomModel).asVarying();
|
||||
const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomFrame).asVarying();
|
||||
task.addJob<BloomEffect>("Bloom", bloomInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
|
@ -261,11 +263,11 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
|
||||
task.addJob<DrawBounds>("DrawLightBounds", lights);
|
||||
task.addJob<DrawBounds>("DrawZones", zones);
|
||||
const auto frustums = task.addJob<ExtractFrustums>("ExtractFrustums");
|
||||
const auto viewFrustum = frustums.getN<ExtractFrustums::Output>(ExtractFrustums::VIEW_FRUSTUM);
|
||||
const auto frustums = task.addJob<ExtractFrustums>("ExtractFrustums", lightFrame);
|
||||
const auto viewFrustum = frustums.getN<ExtractFrustums::Outputs>(ExtractFrustums::VIEW_FRUSTUM);
|
||||
task.addJob<DrawFrustum>("DrawViewFrustum", viewFrustum, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
for (auto i = 0; i < ExtractFrustums::SHADOW_CASCADE_FRUSTUM_COUNT; i++) {
|
||||
const auto shadowFrustum = frustums.getN<ExtractFrustums::Output>(ExtractFrustums::SHADOW_CASCADE0_FRUSTUM + i);
|
||||
const auto shadowFrustum = frustums.getN<ExtractFrustums::Outputs>(ExtractFrustums::SHADOW_CASCADE0_FRUSTUM + i);
|
||||
float tint = 1.0f - i / float(ExtractFrustums::SHADOW_CASCADE_FRUSTUM_COUNT - 1);
|
||||
char jobName[64];
|
||||
sprintf(jobName, "DrawShadowFrustum%d", i);
|
||||
|
@ -290,7 +292,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// Debugging stages
|
||||
{
|
||||
// Debugging Deferred buffer job
|
||||
const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, velocityBuffer, deferredFrameTransform));
|
||||
const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, velocityBuffer, deferredFrameTransform, lightFrame));
|
||||
task.addJob<DebugDeferredBuffer>("DebugDeferredBuffer", debugFramebuffers);
|
||||
|
||||
const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||
|
@ -315,7 +317,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawStatus>("DrawStatus", drawStatusInputs, DrawStatus(statusIconMap));
|
||||
}
|
||||
|
||||
task.addJob<DebugZoneLighting>("DrawZoneStack", deferredFrameTransform);
|
||||
const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying();
|
||||
task.addJob<DebugZoneLighting>("DrawZoneStack", debugZoneInputs);
|
||||
}
|
||||
|
||||
// Upscale to finale resolution
|
||||
|
@ -351,9 +354,11 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
|
||||
|
||||
const auto& inItems = inputs.get0();
|
||||
const auto& lightingModel = inputs.get1();
|
||||
const auto& lightClusters = inputs.get2();
|
||||
const auto jitter = inputs.get3();
|
||||
const auto& hazeFrame = inputs.get1();
|
||||
const auto& lightFrame = inputs.get2();
|
||||
const auto& lightingModel = inputs.get3();
|
||||
const auto& lightClusters = inputs.get4();
|
||||
const auto jitter = inputs.get5();
|
||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
@ -378,13 +383,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
batch.setUniformBuffer(ru::Buffer::LightModel, lightingModel->getParametersBuffer());
|
||||
|
||||
// Set the light
|
||||
deferredLightingEffect->setupKeyLightBatch(args, batch);
|
||||
deferredLightingEffect->setupKeyLightBatch(args, batch, *lightFrame);
|
||||
deferredLightingEffect->setupLocalLightsBatch(batch, lightClusters);
|
||||
|
||||
// Setup haze if current zone has haze
|
||||
auto hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) {
|
||||
graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front());
|
||||
const auto& hazeStage = args->_scene->getStage<HazeStage>();
|
||||
if (hazeStage && hazeFrame->_hazes.size() > 0) {
|
||||
const auto& hazePointer = hazeStage->getHaze(hazeFrame->_hazes.front());
|
||||
if (hazePointer) {
|
||||
batch.setUniformBuffer(ru::Buffer::HazeParams, hazePointer->getHazeParametersBuffer());
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "LightingModel.h"
|
||||
#include "LightClusters.h"
|
||||
#include "RenderShadowTask.h"
|
||||
#include "HazeStage.h"
|
||||
|
||||
class DrawDeferredConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
|
@ -42,7 +43,7 @@ protected:
|
|||
|
||||
class DrawDeferred {
|
||||
public:
|
||||
using Inputs = render::VaryingSet4<render::ItemBounds, LightingModelPointer, LightClustersPointer, glm::vec2>;
|
||||
using Inputs = render::VaryingSet6<render::ItemBounds, HazeStage::FramePointer, LightStage::FramePointer, LightingModelPointer, LightClustersPointer, glm::vec2>;
|
||||
using Config = DrawDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<DrawDeferred, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "FramebufferCache.h"
|
||||
#include "TextureCache.h"
|
||||
#include "RenderCommonTask.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
namespace ru {
|
||||
using render_utils::slot::texture::Texture;
|
||||
|
@ -59,13 +58,13 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
// Extract opaques / transparents / lights / metas / overlays / background
|
||||
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& 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& spatialSelection = items[1];
|
||||
|
||||
fadeEffect->build(task, opaques);
|
||||
|
||||
|
@ -76,10 +75,17 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
// Filter zones from the general metas bucket
|
||||
const auto zones = task.addJob<ZoneRendererTask>("ZoneRenderer", metas);
|
||||
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
const auto backgroundFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(1);
|
||||
//const auto hazeFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(2);
|
||||
//const auto bloomFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(3);
|
||||
|
||||
// GPU jobs: Start preparing the main framebuffer
|
||||
const auto framebuffer = task.addJob<PrepareFramebuffer>("PrepareFramebuffer");
|
||||
|
||||
task.addJob<PrepareForward>("PrepareForward", lightingModel);
|
||||
task.addJob<PrepareForward>("PrepareForward", lightFrame);
|
||||
|
||||
// draw a stencil mask in hidden regions of the framebuffer.
|
||||
task.addJob<PrepareStencil>("PrepareStencil", framebuffer);
|
||||
|
@ -101,7 +107,8 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
task.addJob<DrawForward>("DrawOpaques", opaqueInputs, shapePlumber);
|
||||
|
||||
// Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job
|
||||
task.addJob<DrawBackgroundStage>("DrawBackgroundDeferred", lightingModel);
|
||||
const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying();
|
||||
task.addJob<DrawBackgroundStage>("DrawBackgroundForward", backgroundInputs);
|
||||
|
||||
// Draw transparent objects forward
|
||||
const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel).asVarying();
|
||||
|
@ -114,8 +121,8 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
task.addJob<DrawBounds>("DrawTransparentBounds", transparents);
|
||||
|
||||
task.addJob<DrawBounds>("DrawZones", zones);
|
||||
task.addJob<DebugZoneLighting>("DrawZoneStack", deferredFrameTransform);
|
||||
|
||||
const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying();
|
||||
task.addJob<DebugZoneLighting>("DrawZoneStack", debugZoneInputs);
|
||||
}
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
|
@ -180,12 +187,12 @@ void PrepareForward::run(const RenderContextPointer& renderContext, const Inputs
|
|||
graphics::LightPointer keySunLight;
|
||||
auto lightStage = args->_scene->getStage<LightStage>();
|
||||
if (lightStage) {
|
||||
keySunLight = lightStage->getCurrentKeyLight();
|
||||
keySunLight = lightStage->getCurrentKeyLight(*inputs);
|
||||
}
|
||||
|
||||
graphics::LightPointer keyAmbiLight;
|
||||
if (lightStage) {
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight();
|
||||
keyAmbiLight = lightStage->getCurrentAmbientLight(*inputs);
|
||||
}
|
||||
|
||||
if (keySunLight) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <gpu/Pipeline.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include "LightingModel.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
class RenderForwardTask {
|
||||
public:
|
||||
|
@ -40,7 +41,7 @@ private:
|
|||
|
||||
class PrepareForward {
|
||||
public:
|
||||
using Inputs = LightingModelPointer;
|
||||
using Inputs = LightStage::FramePointer;
|
||||
using JobModel = render::Job::ModelI<PrepareForward, Inputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext,
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "RenderUtilsLogging.h"
|
||||
|
||||
#include "RenderCommonTask.h"
|
||||
|
||||
// These values are used for culling the objects rendered in the shadow map
|
||||
// but are readjusted afterwards
|
||||
#define SHADOW_FRUSTUM_NEAR 1.0f
|
||||
|
@ -40,10 +42,6 @@ void RenderShadowTask::configure(const Config& configuration) {
|
|||
}
|
||||
|
||||
void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cameraCullFunctor, uint8_t tagBits, uint8_t tagMask) {
|
||||
::CullFunctor shadowCullFunctor = [this](const RenderArgs* args, const AABox& bounds) {
|
||||
return _cullFunctor(args, bounds);
|
||||
};
|
||||
|
||||
// Prepare the ShapePipeline
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
{
|
||||
|
@ -54,7 +52,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
initZPassPipelines(*shapePlumber, state);
|
||||
}
|
||||
|
||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||
// FIXME: calling this here before the zones/lights are drawn during the deferred/forward passes means we're actually using the frames from the previous draw
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
|
||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup", lightFrame);
|
||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(1);
|
||||
// Fetch and cull the items from the scene
|
||||
|
||||
|
@ -89,7 +92,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||
char jobName[64];
|
||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, i, _cullFunctor, tagBits, tagMask);
|
||||
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, lightFrame, i, tagBits, tagMask);
|
||||
const auto shadowFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(0);
|
||||
auto antiFrustum = render::Varying(ViewFrustumPointer());
|
||||
cascadeFrustums[i] = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(1);
|
||||
|
@ -97,14 +100,15 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
antiFrustum = cascadeFrustums[i - 2];
|
||||
}
|
||||
|
||||
// CPU jobs: finer grained culling
|
||||
const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum).asVarying();
|
||||
const auto cullInputs = CullShadowBounds::Inputs(sortedShapes, shadowFilter, antiFrustum, lightFrame, cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(2)).asVarying();
|
||||
sprintf(jobName, "CullShadowCascade%d", i);
|
||||
const auto culledShadowItemsAndBounds = task.addJob<CullShadowBounds>(jobName, cullInputs, shadowCullFunctor);
|
||||
const auto culledShadowItemsAndBounds = task.addJob<CullShadowBounds>(jobName, cullInputs);
|
||||
|
||||
// GPU jobs: Render to shadow map
|
||||
sprintf(jobName, "RenderShadowMap%d", i);
|
||||
task.addJob<RenderShadowMap>(jobName, culledShadowItemsAndBounds, shapePlumber, i);
|
||||
const auto shadowInputs = RenderShadowMap::Inputs(culledShadowItemsAndBounds.getN<CullShadowBounds::Outputs>(0),
|
||||
culledShadowItemsAndBounds.getN<CullShadowBounds::Outputs>(1), lightFrame).asVarying();
|
||||
task.addJob<RenderShadowMap>(jobName, shadowInputs, shapePlumber, i);
|
||||
sprintf(jobName, "ShadowCascadeTeardown%d", i);
|
||||
task.addJob<RenderShadowCascadeTeardown>(jobName, shadowFilter);
|
||||
|
||||
|
@ -204,11 +208,12 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con
|
|||
|
||||
const auto& inShapes = inputs.get0();
|
||||
const auto& inShapeBounds = inputs.get1();
|
||||
const auto& lightFrame = inputs.get2();
|
||||
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
|
||||
auto shadow = lightStage->getCurrentKeyShadow();
|
||||
auto shadow = lightStage->getCurrentKeyShadow(*lightFrame);
|
||||
if (!shadow || _cascadeIndex >= shadow->getCascadeCount()) {
|
||||
return;
|
||||
}
|
||||
|
@ -328,11 +333,12 @@ void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) {
|
|||
_bias[cascadeIndex]._slope = value * value * value * 0.01f;
|
||||
}
|
||||
|
||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output) {
|
||||
// Abort all jobs if not casting shadows
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
auto lightFrame = *input;
|
||||
assert(lightStage);
|
||||
if (!lightStage->getCurrentKeyLight() || !lightStage->getCurrentKeyLight()->getCastShadows()) {
|
||||
if (!lightStage->getCurrentKeyLight(lightFrame) || !lightStage->getCurrentKeyLight(lightFrame)->getCastShadows()) {
|
||||
renderContext->taskFlow.abortTask();
|
||||
return;
|
||||
}
|
||||
|
@ -346,7 +352,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
|||
*_cameraFrustum = args->getViewFrustum();
|
||||
output.edit2() = _cameraFrustum;
|
||||
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow(lightFrame);
|
||||
if (globalShadow) {
|
||||
globalShadow->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
||||
|
||||
|
@ -413,15 +419,18 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
|||
}
|
||||
}
|
||||
|
||||
void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
||||
void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output) {
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
const auto& lightFrame = *input;
|
||||
assert(lightStage);
|
||||
|
||||
// Cache old render args
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
||||
RenderShadowTask::CullFunctor cullFunctor;
|
||||
|
||||
const auto globalShadow = lightStage->getCurrentKeyShadow(lightFrame);
|
||||
if (globalShadow && _cascadeIndex < globalShadow->getCascadeCount()) {
|
||||
// Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers)
|
||||
output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask);
|
||||
|
||||
|
@ -434,13 +443,14 @@ void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderCon
|
|||
const auto minTexelCount = 24.0f;
|
||||
// TODO : maybe adapt that with LOD management system?
|
||||
texelSize *= minTexelCount;
|
||||
_cullFunctor._minSquareSize = texelSize * texelSize;
|
||||
cullFunctor._minSquareSize = texelSize * texelSize;
|
||||
|
||||
output.edit1() = cascadeFrustum;
|
||||
} else {
|
||||
output.edit0() = ItemFilter::Builder::nothing();
|
||||
output.edit1() = ViewFrustumPointer();
|
||||
}
|
||||
output.edit2() = cullFunctor;
|
||||
}
|
||||
|
||||
void RenderShadowCascadeTeardown::run(const render::RenderContextPointer& renderContext, const Input& input) {
|
||||
|
@ -498,13 +508,20 @@ void CullShadowBounds::run(const render::RenderContextPointer& renderContext, co
|
|||
outShapes.clear();
|
||||
outBounds = AABox();
|
||||
|
||||
const auto& lightFrame = *inputs.get3();
|
||||
auto cullFunctor = inputs.get4();
|
||||
|
||||
render::CullFunctor shadowCullFunctor = [cullFunctor](const RenderArgs* args, const AABox& bounds) {
|
||||
return cullFunctor(args, bounds);
|
||||
};
|
||||
|
||||
if (!filter.selectsNothing()) {
|
||||
auto& details = args->_details.edit(RenderDetails::SHADOW);
|
||||
render::CullTest test(_cullFunctor, args, details, antiFrustum);
|
||||
render::CullTest test(shadowCullFunctor, args, details, antiFrustum);
|
||||
auto scene = args->_scene;
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
const auto globalLightDir = lightStage->getCurrentKeyLight()->getDirection();
|
||||
const auto globalLightDir = lightStage->getCurrentKeyLight(lightFrame)->getDirection();
|
||||
auto castersFilter = render::ItemFilter::Builder(filter).withShadowCaster().build();
|
||||
const auto& receiversFilter = filter;
|
||||
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
#include "Shadows_shared.slh"
|
||||
|
||||
#include "LightStage.h"
|
||||
|
||||
class ViewFrustum;
|
||||
|
||||
class RenderShadowMap {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<render::ShapeBounds, AABox>;
|
||||
using Inputs = render::VaryingSet3<render::ShapeBounds, AABox, LightStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<RenderShadowMap, Inputs>;
|
||||
|
||||
RenderShadowMap(render::ShapePlumberPointer shapePlumber, unsigned int cascadeIndex) : _shapePlumber{ shapePlumber }, _cascadeIndex{ cascadeIndex } {}
|
||||
|
@ -98,13 +100,14 @@ signals:
|
|||
|
||||
class RenderShadowSetup {
|
||||
public:
|
||||
using Inputs = LightStage::FramePointer;
|
||||
using Outputs = render::VaryingSet3<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer>;
|
||||
using Config = RenderShadowSetupConfig;
|
||||
using JobModel = render::Job::ModelO<RenderShadowSetup, Outputs, Config>;
|
||||
using JobModel = render::Job::ModelIO<RenderShadowSetup, Inputs, Outputs, Config>;
|
||||
|
||||
RenderShadowSetup();
|
||||
void configure(const Config& configuration);
|
||||
void run(const render::RenderContextPointer& renderContext, Outputs& output);
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -121,19 +124,19 @@ private:
|
|||
|
||||
class RenderShadowCascadeSetup {
|
||||
public:
|
||||
using Outputs = render::VaryingSet2<render::ItemFilter, ViewFrustumPointer>;
|
||||
using JobModel = render::Job::ModelO<RenderShadowCascadeSetup, Outputs>;
|
||||
using Inputs = LightStage::FramePointer;
|
||||
using Outputs = render::VaryingSet3<render::ItemFilter, ViewFrustumPointer, RenderShadowTask::CullFunctor>;
|
||||
using JobModel = render::Job::ModelIO<RenderShadowCascadeSetup, Inputs, Outputs>;
|
||||
|
||||
RenderShadowCascadeSetup(unsigned int cascadeIndex, RenderShadowTask::CullFunctor& cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) :
|
||||
_cascadeIndex{ cascadeIndex }, _cullFunctor{ cullFunctor }, _tagBits(tagBits), _tagMask(tagMask) {}
|
||||
void run(const render::RenderContextPointer& renderContext, Outputs& output);
|
||||
RenderShadowCascadeSetup(unsigned int cascadeIndex, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00) :
|
||||
_cascadeIndex(cascadeIndex), _tagBits(tagBits), _tagMask(tagMask) {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output);
|
||||
|
||||
private:
|
||||
|
||||
unsigned int _cascadeIndex;
|
||||
RenderShadowTask::CullFunctor& _cullFunctor;
|
||||
uint8_t _tagBits{ 0x00 };
|
||||
uint8_t _tagMask{ 0x00 };
|
||||
uint8_t _tagBits { 0x00 };
|
||||
uint8_t _tagMask { 0x00 };
|
||||
};
|
||||
|
||||
class RenderShadowCascadeTeardown {
|
||||
|
@ -152,20 +155,11 @@ public:
|
|||
|
||||
class CullShadowBounds {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer>;
|
||||
using Inputs = render::VaryingSet5<render::ShapeBounds, render::ItemFilter, ViewFrustumPointer, LightStage::FramePointer, RenderShadowTask::CullFunctor>;
|
||||
using Outputs = render::VaryingSet2<render::ShapeBounds, AABox>;
|
||||
using JobModel = render::Job::ModelIO<CullShadowBounds, Inputs, Outputs>;
|
||||
|
||||
CullShadowBounds(render::CullFunctor cullFunctor) :
|
||||
_cullFunctor{ cullFunctor } {
|
||||
}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
|
||||
|
||||
private:
|
||||
|
||||
render::CullFunctor _cullFunctor;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_RenderShadowTask_h
|
||||
|
|
|
@ -39,28 +39,16 @@ namespace gr {
|
|||
|
||||
using namespace render;
|
||||
|
||||
class SetupZones {
|
||||
public:
|
||||
using Inputs = render::ItemBounds;
|
||||
using JobModel = render::Job::ModelI<SetupZones, Inputs>;
|
||||
|
||||
SetupZones() {}
|
||||
|
||||
void run(const RenderContextPointer& context, const Inputs& inputs);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
const Selection::Name ZoneRendererTask::ZONES_SELECTION { "RankedZones" };
|
||||
|
||||
void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& ouput) {
|
||||
void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& output) {
|
||||
// Filter out the sorted list of zones
|
||||
const auto zoneItems = task.addJob<render::SelectSortItems>("FilterZones", input, ZONES_SELECTION.c_str());
|
||||
|
||||
// just setup the current zone env
|
||||
task.addJob<SetupZones>("SetupZones", zoneItems);
|
||||
|
||||
ouput = zoneItems;
|
||||
output = zoneItems;
|
||||
}
|
||||
|
||||
void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) {
|
||||
|
@ -130,27 +118,29 @@ const gpu::PipelinePointer& DebugZoneLighting::getBackgroundPipeline() {
|
|||
void DebugZoneLighting::run(const render::RenderContextPointer& context, const Inputs& inputs) {
|
||||
RenderArgs* args = context->args;
|
||||
|
||||
auto deferredTransform = inputs;
|
||||
auto deferredTransform = inputs.get0();
|
||||
auto lightFrame = inputs.get1();
|
||||
auto backgroundFrame = inputs.get2();
|
||||
|
||||
auto lightStage = context->_scene->getStage<LightStage>(LightStage::getName());
|
||||
std::vector<graphics::LightPointer> keyLightStack;
|
||||
if (lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||
for (auto index : lightStage->_currentFrame._sunLights) {
|
||||
if (lightStage && lightFrame->_sunLights.size()) {
|
||||
for (auto index : lightFrame->_sunLights) {
|
||||
keyLightStack.push_back(lightStage->getLight(index));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<graphics::LightPointer> ambientLightStack;
|
||||
if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
|
||||
for (auto index : lightStage->_currentFrame._ambientLights) {
|
||||
if (lightStage && lightFrame->_ambientLights.size()) {
|
||||
for (auto index : lightFrame->_ambientLights) {
|
||||
ambientLightStack.push_back(lightStage->getLight(index));
|
||||
}
|
||||
}
|
||||
|
||||
auto backgroundStage = context->_scene->getStage<BackgroundStage>(BackgroundStage::getName());
|
||||
std::vector<graphics::SkyboxPointer> skyboxStack;
|
||||
if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) {
|
||||
for (auto index : backgroundStage->_currentFrame._backgrounds) {
|
||||
if (backgroundStage && backgroundFrame->_backgrounds.size()) {
|
||||
for (auto index : backgroundFrame->_backgrounds) {
|
||||
auto background = backgroundStage->getBackground(index);
|
||||
if (background) {
|
||||
skyboxStack.push_back(background->getSkybox());
|
||||
|
@ -158,7 +148,6 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
gpu::doInBatch("DebugZoneLighting::run", args->_context, [=](gpu::Batch& batch) {
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
|
|
@ -16,6 +16,19 @@
|
|||
|
||||
#include "DeferredFrameTransform.h"
|
||||
|
||||
#include "LightStage.h"
|
||||
#include "BackgroundStage.h"
|
||||
|
||||
class SetupZones {
|
||||
public:
|
||||
using Inputs = render::ItemBounds;
|
||||
using JobModel = render::Job::ModelI<SetupZones, Inputs>;
|
||||
|
||||
SetupZones() {}
|
||||
|
||||
void run(const render::RenderContextPointer& context, const Inputs& inputs);
|
||||
};
|
||||
|
||||
class ZoneRendererConfig : public render::Task::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty)
|
||||
|
@ -44,7 +57,7 @@ public:
|
|||
|
||||
ZoneRendererTask() {}
|
||||
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& output);
|
||||
|
||||
void configure(const Config& config) { _maxDrawn = config.maxDrawn; }
|
||||
|
||||
|
@ -59,7 +72,7 @@ public:
|
|||
Config(bool enabled = false) : JobConfig(enabled) {}
|
||||
};
|
||||
|
||||
using Inputs = DeferredFrameTransformPointer;
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, LightStage::FramePointer, BackgroundStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelI<DebugZoneLighting, Inputs, Config>;
|
||||
|
||||
DebugZoneLighting() {}
|
||||
|
|
|
@ -132,8 +132,6 @@ QUrl PathUtils::expandToLocalDataAbsolutePath(const QUrl& fileUrl) {
|
|||
return expandedURL;
|
||||
}
|
||||
|
||||
QUrl::fromLocalFile(resourcesPath()).toString();
|
||||
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
|
|
|
@ -418,6 +418,7 @@ protected:
|
|||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5 > using VaryingSet6 = task::VaryingSet6<T0, T1, T2, T3, T4, T5>; \
|
||||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7<T0, T1, T2, T3, T4, T5, T6>; \
|
||||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8<T0, T1, T2, T3, T4, T5, T6, T7>; \
|
||||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > using VaryingSet9 = task::VaryingSet9<T0, T1, T2, T3, T4, T5, T6, T7, T8>; \
|
||||
template < class T, int NUM > using VaryingArray = task::VaryingArray<T, NUM>;
|
||||
|
||||
|
||||
|
|
|
@ -328,6 +328,45 @@ public:
|
|||
Varying asVarying() const { return Varying((*this)); }
|
||||
};
|
||||
|
||||
template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
class VaryingSet9 : public std::tuple<Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying> {
|
||||
public:
|
||||
using Parent = std::tuple<Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying>;
|
||||
|
||||
VaryingSet9() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6()), Varying(T7()), Varying(T8())) {}
|
||||
VaryingSet9(const VaryingSet9& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src), std::get<7>(src), std::get<8>(src)) {}
|
||||
VaryingSet9(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh, const Varying& eighth, const Varying& nine) : Parent(first, second, third, fourth, fifth, sixth, seventh, eighth, nine) {}
|
||||
|
||||
const T0& get0() const { return std::get<0>((*this)).template get<T0>(); }
|
||||
T0& edit0() { return std::get<0>((*this)).template edit<T0>(); }
|
||||
|
||||
const T1& get1() const { return std::get<1>((*this)).template get<T1>(); }
|
||||
T1& edit1() { return std::get<1>((*this)).template edit<T1>(); }
|
||||
|
||||
const T2& get2() const { return std::get<2>((*this)).template get<T2>(); }
|
||||
T2& edit2() { return std::get<2>((*this)).template edit<T2>(); }
|
||||
|
||||
const T3& get3() const { return std::get<3>((*this)).template get<T3>(); }
|
||||
T3& edit3() { return std::get<3>((*this)).template edit<T3>(); }
|
||||
|
||||
const T4& get4() const { return std::get<4>((*this)).template get<T4>(); }
|
||||
T4& edit4() { return std::get<4>((*this)).template edit<T4>(); }
|
||||
|
||||
const T5& get5() const { return std::get<5>((*this)).template get<T5>(); }
|
||||
T5& edit5() { return std::get<5>((*this)).template edit<T5>(); }
|
||||
|
||||
const T6& get6() const { return std::get<6>((*this)).template get<T6>(); }
|
||||
T6& edit6() { return std::get<6>((*this)).template edit<T6>(); }
|
||||
|
||||
const T7& get7() const { return std::get<7>((*this)).template get<T7>(); }
|
||||
T7& edit7() { return std::get<7>((*this)).template edit<T7>(); }
|
||||
|
||||
const T8& get8() const { return std::get<8>((*this)).template get<T8>(); }
|
||||
T8& edit8() { return std::get<8>((*this)).template edit<T8>(); }
|
||||
|
||||
Varying asVarying() const { return Varying((*this)); }
|
||||
};
|
||||
|
||||
template < class T, int NUM >
|
||||
class VaryingArray : public std::array<Varying, NUM> {
|
||||
public:
|
||||
|
|
|
@ -244,7 +244,7 @@ input.search:focus {
|
|||
height: 26px;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
box-shadow: 0 0 0px 1px #00b4ef;
|
||||
box-shadow: 0 0 0 1px #00b4ef;
|
||||
}
|
||||
|
||||
input:disabled, textarea:disabled {
|
||||
|
@ -455,11 +455,11 @@ input[type=checkbox]:checked + label:hover {
|
|||
#properties-list fieldset {
|
||||
position: relative;
|
||||
/* 0.1px on the top is to prevent margin collapsing between this and it's first child */
|
||||
margin: 21px -21px 0px -21px;
|
||||
padding: 0.1px 21px 0px 21px;
|
||||
margin: 21px -21px 0 -21px;
|
||||
padding: 0.1px 21px 0 21px;
|
||||
border: none;
|
||||
border-top: 1px rgb(90,90,90) solid;
|
||||
box-shadow: 0px -1px 0px rgb(37,37,37);
|
||||
box-shadow: 0 -1px 0 rgb(37,37,37);
|
||||
}
|
||||
|
||||
#properties-list fieldset.fstuple, #properties-list fieldset.fsrow {
|
||||
|
@ -469,7 +469,7 @@ input[type=checkbox]:checked + label:hover {
|
|||
}
|
||||
|
||||
#properties-list > fieldset[data-collapsed="true"] + fieldset {
|
||||
margin-top: 0px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#properties-list > fieldset[data-collapsed="true"] > *:not(legend) {
|
||||
|
@ -477,14 +477,14 @@ input[type=checkbox]:checked + label:hover {
|
|||
}
|
||||
|
||||
#properties-list legend + fieldset {
|
||||
margin-top: 0px;
|
||||
margin-top: 0;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#properties-list > fieldset#properties-header {
|
||||
margin-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -940,8 +940,8 @@ tuple, .blue:focus, .tuple .z:focus, .tuple .roll:focus {
|
|||
#properties-list .two-column fieldset legend {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin: 21px -21px 0px -21px;
|
||||
padding: 0px 0px 0px 21px;
|
||||
margin: 21px -21px 0 -21px;
|
||||
padding: 0 0 0 21px;
|
||||
font-family: Raleway-Regular;
|
||||
font-size: 12px;
|
||||
color: #afafaf;
|
||||
|
@ -973,6 +973,10 @@ fieldset .checkbox-sub-props .property:first-child {
|
|||
::-webkit-scrollbar-track {
|
||||
background-color: #2e2e2e;
|
||||
}
|
||||
#entity-table-scroll::-webkit-scrollbar-track {
|
||||
border-bottom-right-radius: 7px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #696969;
|
||||
border: 2px solid #2e2e2e;
|
||||
|
@ -1031,6 +1035,16 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
position: relative; /* New positioning context. */
|
||||
}
|
||||
|
||||
#footer-text {
|
||||
float: right;
|
||||
padding-top: 12px;
|
||||
padding-right: 22px;
|
||||
}
|
||||
|
||||
#entity-list-footer {
|
||||
padding-top: 9px;
|
||||
}
|
||||
|
||||
#search-area {
|
||||
padding-right: 168px;
|
||||
padding-bottom: 24px;
|
||||
|
@ -1068,6 +1082,9 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
margin-top: 28px;
|
||||
border-left: 2px solid #575757;
|
||||
border-right: 2px solid #575757;
|
||||
border-bottom: 2px solid #575757;
|
||||
border-bottom-left-radius: 7px;
|
||||
border-bottom-right-radius: 7px;
|
||||
background-color: #1c1c1c;
|
||||
}
|
||||
|
||||
|
@ -1084,8 +1101,7 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
background-color: #1c1c1c;
|
||||
}
|
||||
|
||||
#entity-table thead tr, #entity-table thead tr th,
|
||||
#entity-table tfoot tr, #entity-table tfoot tr td {
|
||||
#entity-table thead tr, #entity-table thead tr th {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
@ -1196,19 +1212,6 @@ th#entity-hasTransparent .sort-order {
|
|||
top: -1px;
|
||||
}
|
||||
|
||||
#entity-table tfoot {
|
||||
box-sizing: border-box;
|
||||
border: 2px solid #575757;
|
||||
border-bottom-left-radius: 7px;
|
||||
border-bottom-right-radius: 7px;
|
||||
border-top: 1px solid #575757;
|
||||
position: absolute;
|
||||
bottom: -21px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
#col-type {
|
||||
width: 16%;
|
||||
}
|
||||
|
@ -1788,4 +1791,13 @@ input#reset-to-natural-dimensions {
|
|||
|
||||
.skybox-section {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=button]#export {
|
||||
height: 38px;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
body#entity-list-body {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!--
|
||||
<!--
|
||||
// entityList.html
|
||||
//
|
||||
// Created by Ryan Huffman on 19 Nov 2014
|
||||
|
@ -18,14 +18,13 @@
|
|||
<script type="text/javascript" src="js/listView.js"></script>
|
||||
<script type="text/javascript" src="js/entityList.js"></script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<body onload='loaded();' id="entity-list-body">
|
||||
<div id="entity-list-header">
|
||||
<input type="button" class="glyph" id="refresh" value="F" />
|
||||
<div>
|
||||
<input type="button" id="locked" class="glyph" value="" />
|
||||
<input type="button" id="visible" class="glyph" value="" />
|
||||
</div>
|
||||
<input type="button" id="export" value="Export Selection" />
|
||||
<input type="button" id="pal" class="glyph" value="" />
|
||||
<input type="button" class="red" id="delete" value="Delete" />
|
||||
</div>
|
||||
|
@ -87,11 +86,6 @@
|
|||
<td class="id" style="display: none"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td id="footer-text" colspan="12"> </td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<div id="no-entities">
|
||||
|
@ -99,5 +93,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="entity-list-footer">
|
||||
<div>
|
||||
<input type="button" id="export" value="Export Selection" />
|
||||
<div id="footer-text">
|
||||
<b><span id="selected-entities-count">0</span> of <span id="visible-entities-count">0</span></b> selected
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -20,7 +20,7 @@ const IMAGE_MODEL_NAME = 'default-image-model.fbx';
|
|||
const COLLAPSE_EXTRA_INFO = "E";
|
||||
const EXPAND_EXTRA_INFO = "D";
|
||||
const FILTER_IN_VIEW_ATTRIBUTE = "pressed";
|
||||
const WINDOW_NONVARIABLE_HEIGHT = 207;
|
||||
const WINDOW_NONVARIABLE_HEIGHT = 227;
|
||||
const NUM_COLUMNS = 12;
|
||||
const EMPTY_ENTITY_ID = "0";
|
||||
const DELETE = 46; // Key code for the delete key.
|
||||
|
@ -60,7 +60,7 @@ const COMPARE_DESCENDING = function(a, b) {
|
|||
}
|
||||
|
||||
// List of all entities
|
||||
var entities = []
|
||||
var entities = [];
|
||||
// List of all entities, indexed by Entity ID
|
||||
var entitiesByID = {};
|
||||
// The filtered and sorted list of entities passed to ListView
|
||||
|
@ -112,7 +112,8 @@ function loaded() {
|
|||
elPal = document.getElementById("pal");
|
||||
elInfoToggle = document.getElementById("info-toggle");
|
||||
elInfoToggleGlyph = elInfoToggle.firstChild;
|
||||
elFooter = document.getElementById("footer-text");
|
||||
elSelectedEntitiesCount = document.getElementById("selected-entities-count");
|
||||
elVisibleEntitiesCount = document.getElementById("visible-entities-count");
|
||||
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||
elNoEntitiesInView = document.getElementById("no-entities-in-view");
|
||||
elNoEntitiesRadius = document.getElementById("no-entities-radius");
|
||||
|
@ -440,15 +441,8 @@ function loaded() {
|
|||
}
|
||||
|
||||
function refreshFooter() {
|
||||
if (selectedEntities.length > 1) {
|
||||
elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected";
|
||||
} else if (selectedEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity selected";
|
||||
} else if (visibleEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity found";
|
||||
} else {
|
||||
elFooter.firstChild.nodeValue = visibleEntities.length + " entities found";
|
||||
}
|
||||
elSelectedEntitiesCount.innerText = selectedEntities.length;
|
||||
elVisibleEntitiesCount.innerText = visibleEntities.length;
|
||||
}
|
||||
|
||||
function refreshNoEntitiesMessage() {
|
||||
|
@ -646,7 +640,7 @@ function loaded() {
|
|||
data = JSON.parse(data);
|
||||
if (data.type === "clearEntityList") {
|
||||
clearEntities();
|
||||
} else if (data.type == "selectionUpdate") {
|
||||
} else if (data.type === "selectionUpdate") {
|
||||
let notFound = updateSelectedEntities(data.selectedIDs);
|
||||
if (notFound) {
|
||||
refreshEntities();
|
||||
|
|
|
@ -6,11 +6,5 @@
|
|||
//
|
||||
|
||||
openLoginWindow = function openLoginWindow() {
|
||||
if ((HMD.active && Settings.getValue("hmdTabletBecomesToolbar", false))
|
||||
|| (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) {
|
||||
Menu.triggerOption("Login/Sign Up");
|
||||
} else {
|
||||
tablet.loadQMLOnTop("dialogs/TabletLoginDialog.qml");
|
||||
HMD.openTablet();
|
||||
}
|
||||
Menu.triggerOption("Login/Sign Up");
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue