Merge pull request #1050 from HifiExperiments/zoneProps

Zone properties for tonemapping and ambient occlusion
This commit is contained in:
ksuprynowicz 2024-07-27 16:38:05 +02:00 committed by GitHub
commit 3dad0f14a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 2057 additions and 415 deletions

View file

@ -233,18 +233,17 @@ private:
mutable ReadWriteLockable _renderSettingLock;
// Runtime value of each settings
int _renderMethod{ RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
bool _shadowsEnabled{ true };
bool _ambientOcclusionEnabled{ false };
AntialiasingConfig::Mode _antialiasingMode{ AntialiasingConfig::Mode::NONE };
float _viewportResolutionScale{ 1.0f };
int _renderMethod { RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
bool _shadowsEnabled { true };
bool _ambientOcclusionEnabled { true };
AntialiasingConfig::Mode _antialiasingMode { AntialiasingConfig::Mode::NONE };
float _viewportResolutionScale { 1.0f };
QString _fullScreenScreen;
// Actual settings saved on disk
Setting::Handle<int> _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED };
Setting::Handle<bool> _shadowsEnabledSetting { "shadowsEnabled", true };
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", false };
Setting::Handle<bool> _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", true };
//Setting::Handle<AntialiasingConfig::Mode> _antialiasingModeSetting { "antialiasingMode", AntialiasingConfig::Mode::TAA };
Setting::Handle<int> _antialiasingModeSetting { "antialiasingMode", AntialiasingConfig::Mode::NONE };
Setting::Handle<float> _viewportResolutionScaleSetting { "viewportResolutionScale", 1.0f };

View file

@ -68,6 +68,20 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity
_bloomIndex = INVALID_INDEX;
}
}
if (_tonemappingStage) {
if (!TonemappingStage::isIndexInvalid(_tonemappingIndex)) {
_tonemappingStage->removeTonemapping(_tonemappingIndex);
_tonemappingIndex = INVALID_INDEX;
}
}
if (_ambientOcclusionStage) {
if (!AmbientOcclusionStage::isIndexInvalid(_ambientOcclusionIndex)) {
_ambientOcclusionStage->removeAmbientOcclusion(_ambientOcclusionIndex);
_ambientOcclusionIndex = INVALID_INDEX;
}
}
}
void ZoneEntityRenderer::doRender(RenderArgs* args) {
@ -96,6 +110,16 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
assert(_bloomStage);
}
if (!_tonemappingStage) {
_tonemappingStage = args->_scene->getStage<TonemappingStage>();
assert(_tonemappingStage);
}
if (!_ambientOcclusionStage) {
_ambientOcclusionStage = args->_scene->getStage<AmbientOcclusionStage>();
assert(_ambientOcclusionStage);
}
{ // Sun
if (_needSunUpdate) {
if (LightStage::isIndexInvalid(_sunIndex)) {
@ -149,6 +173,24 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
}
}
{
if (_needTonemappingUpdate) {
if (TonemappingStage::isIndexInvalid(_tonemappingIndex)) {
_tonemappingIndex = _tonemappingStage->addTonemapping(_tonemapping);
}
_needTonemappingUpdate = false;
}
}
{
if (_needAmbientOcclusionUpdate) {
if (AmbientOcclusionStage::isIndexInvalid(_ambientOcclusionIndex)) {
_ambientOcclusionIndex = _ambientOcclusionStage->addAmbientOcclusion(_ambientOcclusion);
}
_needAmbientOcclusionUpdate = false;
}
}
if (_visible) {
// Finally, push the lights visible in the frame
//
@ -184,6 +226,18 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) {
} else if (_bloomMode == COMPONENT_MODE_ENABLED) {
_bloomStage->_currentFrame.pushBloom(_bloomIndex);
}
if (_tonemappingMode == COMPONENT_MODE_DISABLED) {
_tonemappingStage->_currentFrame.pushTonemapping(0); // Use the fallback tonemapping for "off"
} else if (_tonemappingMode == COMPONENT_MODE_ENABLED) {
_tonemappingStage->_currentFrame.pushTonemapping(_tonemappingIndex);
}
if (_ambientOcclusionMode == COMPONENT_MODE_DISABLED) {
_ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(INVALID_INDEX);
} else if (_ambientOcclusionMode == COMPONENT_MODE_ENABLED) {
_ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(_ambientOcclusionIndex);
}
}
CullTest::_containingZones.insert(_entityID);
@ -216,6 +270,8 @@ void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
bool skyboxChanged = entity->skyboxPropertiesChanged() || proceduralUserDataChanged;
bool hazeChanged = entity->hazePropertiesChanged();
bool bloomChanged = entity->bloomPropertiesChanged();
bool tonemappingChanged = entity->tonemappingPropertiesChanged();
bool ambientOcclusionChanged = entity->ambientOcclusionPropertiesChanged();
entity->resetRenderingPropertiesChanged();
if (transformChanged) {
@ -255,6 +311,16 @@ void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
updateBloomFromEntity(entity);
}
if (tonemappingChanged) {
_tonemappingProperties = entity->getTonemappingProperties();
updateTonemappingFromEntity(entity);
}
if (ambientOcclusionChanged) {
_ambientOcclusionProperties = entity->getAmbientOcclusionProperties();
updateAmbientOcclusionFromEntity(entity);
}
bool visuallyReady = true;
uint32_t skyboxMode = entity->getSkyboxMode();
if (skyboxMode == COMPONENT_MODE_ENABLED && !_skyboxTextureURL.isEmpty()) {
@ -275,7 +341,9 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
entity->ambientLightPropertiesChanged() ||
entity->hazePropertiesChanged() ||
entity->bloomPropertiesChanged() ||
entity->skyboxPropertiesChanged()) {
entity->skyboxPropertiesChanged() ||
entity->tonemappingPropertiesChanged() ||
entity->ambientOcclusionPropertiesChanged()) {
return true;
}
@ -360,6 +428,32 @@ void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity)
bloom->setBloomSize(_bloomProperties.getBloomSize());
}
void ZoneEntityRenderer::updateTonemappingFromEntity(const TypedEntityPointer& entity) {
_tonemappingMode = (ComponentMode)entity->getTonemappingMode();
const auto& tonemapping = editTonemapping();
tonemapping->setCurve(_tonemappingProperties.getCurve());
tonemapping->setExposure(_tonemappingProperties.getExposure());
}
void ZoneEntityRenderer::updateAmbientOcclusionFromEntity(const TypedEntityPointer& entity) {
_ambientOcclusionMode = (ComponentMode)entity->getAmbientOcclusionMode();
const auto& ambientOcclusion = editAmbientOcclusion();
ambientOcclusion->setTechnique(_ambientOcclusionProperties.getTechnique());
ambientOcclusion->setJitter(_ambientOcclusionProperties.getJitter());
ambientOcclusion->setResolutionLevel(_ambientOcclusionProperties.getResolutionLevel());
ambientOcclusion->setEdgeSharpness(_ambientOcclusionProperties.getEdgeSharpness());
ambientOcclusion->setBlurRadius(_ambientOcclusionProperties.getBlurRadius());
ambientOcclusion->setAORadius(_ambientOcclusionProperties.getAORadius());
ambientOcclusion->setAOObscuranceLevel(_ambientOcclusionProperties.getAOObscuranceLevel());
ambientOcclusion->setAOFalloffAngle(_ambientOcclusionProperties.getAOFalloffAngle());
ambientOcclusion->setAOSamplingAmount(_ambientOcclusionProperties.getAOSamplingAmount());
ambientOcclusion->setSSAONumSpiralTurns(_ambientOcclusionProperties.getSSAONumSpiralTurns());
}
void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer& entity) {
_skyboxMode = (ComponentMode)entity->getSkyboxMode();

View file

@ -20,6 +20,8 @@
#include <BackgroundStage.h>
#include <HazeStage.h>
#include <BloomStage.h>
#include <TonemappingStage.h>
#include <AmbientOcclusionStage.h>
#include <TextureCache.h>
#include "RenderableEntityItem.h"
#include <ComponentMode.h>
@ -47,6 +49,8 @@ private:
void updateHazeFromEntity(const TypedEntityPointer& entity);
void updateKeyBackgroundFromEntity(const TypedEntityPointer& entity);
void updateBloomFromEntity(const TypedEntityPointer& entity);
void updateTonemappingFromEntity(const TypedEntityPointer& entity);
void updateAmbientOcclusionFromEntity(const TypedEntityPointer& entity);
void updateAmbientMap();
void updateSkyboxMap();
void setAmbientURL(const QString& ambientUrl);
@ -61,6 +65,8 @@ private:
graphics::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); }
graphics::HazePointer editHaze() { _needHazeUpdate = true; return _haze; }
graphics::BloomPointer editBloom() { _needBloomUpdate = true; return _bloom; }
graphics::TonemappingPointer editTonemapping() { _needTonemappingUpdate = true; return _tonemapping; }
graphics::AmbientOcclusionPointer editAmbientOcclusion() { _needAmbientOcclusionUpdate = true; return _ambientOcclusion; }
glm::vec3 _lastPosition;
glm::vec3 _lastDimensions;
@ -73,12 +79,16 @@ private:
const graphics::SunSkyStagePointer _background { std::make_shared<graphics::SunSkyStage>() };
const graphics::HazePointer _haze { std::make_shared<graphics::Haze>() };
const graphics::BloomPointer _bloom { std::make_shared<graphics::Bloom>() };
const graphics::TonemappingPointer _tonemapping { std::make_shared<graphics::Tonemapping>() };
const graphics::AmbientOcclusionPointer _ambientOcclusion { std::make_shared<graphics::AmbientOcclusion>() };
ComponentMode _keyLightMode { COMPONENT_MODE_INHERIT };
ComponentMode _ambientLightMode { COMPONENT_MODE_INHERIT };
ComponentMode _skyboxMode { COMPONENT_MODE_INHERIT };
ComponentMode _hazeMode { COMPONENT_MODE_INHERIT };
ComponentMode _bloomMode { COMPONENT_MODE_INHERIT };
ComponentMode _tonemappingMode { COMPONENT_MODE_INHERIT };
ComponentMode _ambientOcclusionMode { COMPONENT_MODE_INHERIT };
indexed_container::Index _sunIndex { LightStage::INVALID_INDEX };
indexed_container::Index _ambientIndex { LightStage::INVALID_INDEX };
@ -92,27 +102,37 @@ private:
BloomStagePointer _bloomStage;
BloomStage::Index _bloomIndex { BloomStage::INVALID_INDEX };
bool _needUpdate{ true };
bool _needSunUpdate{ true };
bool _needAmbientUpdate{ true };
bool _needBackgroundUpdate{ true };
bool _needHazeUpdate{ true };
TonemappingStagePointer _tonemappingStage;
TonemappingStage::Index _tonemappingIndex { TonemappingStage::INVALID_INDEX };
AmbientOcclusionStagePointer _ambientOcclusionStage;
AmbientOcclusionStage::Index _ambientOcclusionIndex { AmbientOcclusionStage::INVALID_INDEX };
bool _needUpdate { true };
bool _needSunUpdate { true };
bool _needAmbientUpdate { true };
bool _needBackgroundUpdate { true };
bool _needHazeUpdate { true };
bool _needBloomUpdate { true };
bool _needTonemappingUpdate { true };
bool _needAmbientOcclusionUpdate { true };
KeyLightPropertyGroup _keyLightProperties;
AmbientLightPropertyGroup _ambientLightProperties;
HazePropertyGroup _hazeProperties;
SkyboxPropertyGroup _skyboxProperties;
BloomPropertyGroup _bloomProperties;
TonemappingPropertyGroup _tonemappingProperties;
AmbientOcclusionPropertyGroup _ambientOcclusionProperties;
// More attributes used for rendering:
QString _ambientTextureURL;
NetworkTexturePointer _ambientTexture;
bool _pendingAmbientTexture{ false };
bool _pendingAmbientTexture { false };
QString _skyboxTextureURL;
NetworkTexturePointer _skyboxTexture;
bool _pendingSkyboxTexture{ false };
bool _pendingSkyboxTexture { false };
QString _proceduralUserData;
};

View file

@ -0,0 +1,300 @@
//
// AmbientOcclusionPropertyGroup.cpp
// libraries/entities/src
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "AmbientOcclusionPropertyGroup.h"
#include <OctreePacketData.h>
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
inline void addAmbientOcclusionTechnique(QHash<QString, AmbientOcclusionTechnique>& lookup, AmbientOcclusionTechnique technique) { lookup[AmbientOcclusionTechniqueHelpers::getNameForAmbientOcclusionTechnique(technique)] = technique; }
const QHash<QString, AmbientOcclusionTechnique> stringToAmbientOcclusionTechniqueLookup = [] {
QHash<QString, AmbientOcclusionTechnique> toReturn;
addAmbientOcclusionTechnique(toReturn, AmbientOcclusionTechnique::SSAO);
addAmbientOcclusionTechnique(toReturn, AmbientOcclusionTechnique::HBAO);
return toReturn;
}();
QString AmbientOcclusionPropertyGroup::getTechniqueAsString() const { return AmbientOcclusionTechniqueHelpers::getNameForAmbientOcclusionTechnique(_technique); }
void AmbientOcclusionPropertyGroup::setTechniqueFromString(const QString& technique) {
auto techniqueItr = stringToAmbientOcclusionTechniqueLookup.find(technique.toLower());
if (techniqueItr != stringToAmbientOcclusionTechniqueLookup.end()) {
_technique = techniqueItr.value();
_techniqueChanged = true;
}
}
void AmbientOcclusionPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags, bool isMyOwnAvatarEntity) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_OCCLUSION_TECHNIQUE, AmbientOcclusion, ambientOcclusion, Technique, technique, getTechniqueAsString);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_JITTER, AmbientOcclusion, ambientOcclusion, Jitter, jitter);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, AmbientOcclusion, ambientOcclusion, ResolutionLevel, resolutionLevel);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, AmbientOcclusion, ambientOcclusion, EdgeSharpness, edgeSharpness);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, AmbientOcclusion, ambientOcclusion, BlurRadius, blurRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_AO_RADIUS, AmbientOcclusion, ambientOcclusion, AORadius, aoRadius);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, AmbientOcclusion, ambientOcclusion, AOObscuranceLevel, aoObscuranceLevel);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, AmbientOcclusion, ambientOcclusion, AOFalloffAngle, aoFalloffAngle);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, AmbientOcclusion, ambientOcclusion, AOSamplingAmount, aoSamplingAmount);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, AmbientOcclusion, ambientOcclusion, SSAONumSpiralTurns, ssaoNumSpiralTurns);
}
void AmbientOcclusionPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientOcclusion, technique, Technique);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, jitter, bool, setJitter);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, resolutionLevel, uint8_t, setResolutionLevel);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, edgeSharpness, float, setEdgeSharpness);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, blurRadius, uint8_t, setBlurRadius);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, aoRadius, float, setAORadius);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, aoObscuranceLevel, float, setAOObscuranceLevel);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, aoFalloffAngle, float, setAOFalloffAngle);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, aoSamplingAmount, float, setAOSamplingAmount);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientOcclusion, ssaoNumSpiralTurns, float, setSSAONumSpiralTurns);
}
void AmbientOcclusionPropertyGroup::merge(const AmbientOcclusionPropertyGroup& other) {
COPY_PROPERTY_IF_CHANGED(technique);
COPY_PROPERTY_IF_CHANGED(jitter);
COPY_PROPERTY_IF_CHANGED(resolutionLevel);
COPY_PROPERTY_IF_CHANGED(edgeSharpness);
COPY_PROPERTY_IF_CHANGED(blurRadius);
COPY_PROPERTY_IF_CHANGED(aoRadius);
COPY_PROPERTY_IF_CHANGED(aoObscuranceLevel);
COPY_PROPERTY_IF_CHANGED(aoFalloffAngle);
COPY_PROPERTY_IF_CHANGED(aoSamplingAmount);
COPY_PROPERTY_IF_CHANGED(ssaoNumSpiralTurns);
}
void AmbientOcclusionPropertyGroup::debugDump() const {
qCDebug(entities) << " AmbientOcclusionPropertyGroup: ---------------------------------------------";
qCDebug(entities) << " Technique:" << getTechniqueAsString();
qCDebug(entities) << " Jitter:" << getJitter();
qCDebug(entities) << " ResolutionLevel:" << getResolutionLevel();
qCDebug(entities) << " EdgeSharpness:" << getEdgeSharpness();
qCDebug(entities) << " BlurRadius:" << getBlurRadius();
qCDebug(entities) << " AORadius:" << getAORadius();
qCDebug(entities) << " AOObscuranceLevel:" << getAOObscuranceLevel();
qCDebug(entities) << " AOFalloffAngle:" << getAOFalloffAngle();
qCDebug(entities) << " AOSamplingAmount:" << getAOSamplingAmount();
qCDebug(entities) << " SSAONumSpiralTurns:" << getSSAONumSpiralTurns();
}
void AmbientOcclusionPropertyGroup::listChangedProperties(QList<QString>& out) {
if (techniqueChanged()) {
out << "ambientOcclusion-technique";
}
if (jitterChanged()) {
out << "ambientOcclusion-jitter";
}
if (resolutionLevelChanged()) {
out << "ambientOcclusion-resolutionLevel";
}
if (edgeSharpnessChanged()) {
out << "ambientOcclusion-edgeSharpness";
}
if (blurRadiusChanged()) {
out << "ambientOcclusion-blurRadius";
}
if (aoRadiusChanged()) {
out << "ambientOcclusion-aoRadius";
}
if (aoObscuranceLevelChanged()) {
out << "ambientOcclusion-aoObscuranceLevel";
}
if (aoFalloffAngleChanged()) {
out << "ambientOcclusion-aoFalloffAngle";
}
if (aoSamplingAmountChanged()) {
out << "ambientOcclusion-aoSamplingAmount";
}
if (ssaoNumSpiralTurnsChanged()) {
out << "ambientOcclusion-ssaoNumSpiralTurns";
}
}
bool AmbientOcclusionPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_TECHNIQUE, (uint32_t)getTechnique());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_JITTER, getJitter());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, getResolutionLevel());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, getEdgeSharpness());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, getBlurRadius());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_RADIUS, getAORadius());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, getAOObscuranceLevel());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, getAOFalloffAngle());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, getAOSamplingAmount());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, getSSAONumSpiralTurns());
return true;
}
bool AmbientOcclusionPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_TECHNIQUE, AmbientOcclusionTechnique, setTechnique);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_JITTER, bool, setJitter);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, uint8_t, setResolutionLevel);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, float, setEdgeSharpness);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, uint8_t, setBlurRadius);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_RADIUS, float, setAORadius);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, float, setAOObscuranceLevel);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, float, setAOFalloffAngle);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, float, setAOSamplingAmount);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, float, setSSAONumSpiralTurns);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_TECHNIQUE, Technique);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_JITTER, Jitter);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, ResolutionLevel);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, EdgeSharpness);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, BlurRadius);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_AO_RADIUS, AORadius);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, AOObscuranceLevel);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, AOFalloffAngle);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, AOSamplingAmount);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, SSAONumSpiralTurns);
processedBytes += bytesRead;
Q_UNUSED(somethingChanged);
return true;
}
void AmbientOcclusionPropertyGroup::markAllChanged() {
_techniqueChanged = true;
_jitterChanged = true;
_resolutionLevelChanged = true;
_edgeSharpnessChanged = true;
_blurRadiusChanged = true;
_aoRadiusChanged = true;
_aoObscuranceLevelChanged = true;
_aoFalloffAngleChanged = true;
_aoSamplingAmountChanged = true;
_ssaoNumSpiralTurnsChanged = true;
}
EntityPropertyFlags AmbientOcclusionPropertyGroup::getChangedProperties() const {
EntityPropertyFlags changedProperties;
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_TECHNIQUE, technique);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_JITTER, jitter);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, resolutionLevel);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, edgeSharpness);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, blurRadius);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_AO_RADIUS, aoRadius);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, aoObscuranceLevel);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, aoFalloffAngle);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, aoSamplingAmount);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, ssaoNumSpiralTurns);
return changedProperties;
}
void AmbientOcclusionPropertyGroup::getProperties(EntityItemProperties& properties) const {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, Technique, getTechnique);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, Jitter, getJitter);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, ResolutionLevel, getResolutionLevel);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, EdgeSharpness, getEdgeSharpness);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, BlurRadius, getBlurRadius);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, AORadius, getAORadius);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, AOObscuranceLevel, getAOObscuranceLevel);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, AOFalloffAngle, getAOFalloffAngle);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, AOSamplingAmount, getAOSamplingAmount);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientOcclusion, SSAONumSpiralTurns, getSSAONumSpiralTurns);
}
bool AmbientOcclusionPropertyGroup::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, Technique, technique, setTechnique);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, Jitter, jitter, setJitter);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, ResolutionLevel, resolutionLevel, setResolutionLevel);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, EdgeSharpness, edgeSharpness, setEdgeSharpness);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, BlurRadius, blurRadius, setBlurRadius);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, AORadius, aoRadius, setAORadius);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, AOObscuranceLevel, aoObscuranceLevel, setAOObscuranceLevel);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, AOFalloffAngle, aoFalloffAngle, setAOFalloffAngle);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, AOSamplingAmount, aoSamplingAmount, setAOSamplingAmount);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientOcclusion, SSAONumSpiralTurns, ssaoNumSpiralTurns, setSSAONumSpiralTurns);
return somethingChanged;
}
EntityPropertyFlags AmbientOcclusionPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties;
requestedProperties += PROP_AMBIENT_OCCLUSION_TECHNIQUE;
requestedProperties += PROP_AMBIENT_OCCLUSION_JITTER;
requestedProperties += PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL;
requestedProperties += PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS;
requestedProperties += PROP_AMBIENT_OCCLUSION_BLUR_RADIUS;
requestedProperties += PROP_AMBIENT_OCCLUSION_AO_RADIUS;
requestedProperties += PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL;
requestedProperties += PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE;
requestedProperties += PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT;
requestedProperties += PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS;
return requestedProperties;
}
void AmbientOcclusionPropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_TECHNIQUE, (uint32_t)getTechnique());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_JITTER, getJitter());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, getResolutionLevel());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, getEdgeSharpness());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, getBlurRadius());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_RADIUS, getAORadius());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, getAOObscuranceLevel());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, getAOFalloffAngle());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, getAOSamplingAmount());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, getSSAONumSpiralTurns());
}
int AmbientOcclusionPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_TECHNIQUE, AmbientOcclusionTechnique, setTechnique);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_JITTER, bool, setJitter);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, uint8_t, setResolutionLevel);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, float, setEdgeSharpness);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, uint8_t, setBlurRadius);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_RADIUS, float, setAORadius);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, float, setAOObscuranceLevel);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, float, setAOFalloffAngle);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, float, setAOSamplingAmount);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, float, setSSAONumSpiralTurns);
return bytesRead;
}

View file

@ -0,0 +1,108 @@
//
// AmbientOcclusionPropertyGroup.h
// libraries/entities/src
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_AmbientOcclusionPropertyGroup_h
#define hifi_AmbientOcclusionPropertyGroup_h
#include <AmbientOcclusionTechnique.h>
#include "PropertyGroup.h"
#include "EntityItemPropertiesMacros.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
class ScriptEngine;
class ScriptValue;
/*@jsdoc
* AmbientOcclusion is defined by the following properties:
* @typedef {object} Entities.AmbientOcclusion
* @property {AmbientOcclusionTechnique} technique="ssao" - The ambient occlusion technique used. Different techniques have
* different tradeoffs.
* @property {boolean} jitter=false - Whether or not the ambient occlusion sampling is jittered.
* @property {number} resolutionLevel=2 - How high the resolution of the ambient occlusion buffer should be. Higher levels
* mean lower resolution buffers.
* @property {number} edgeSharpness=1.0 - How much to sharpen the edges during the ambient occlusion blurring.
* @property {number} blurRadius=4 - The radius used for blurring, in pixels.
* @property {number} aoRadius=1.0 - The radius used for ambient occlusion.
* @property {number} aoObscuranceLevel=0.5 - Intensify or dim ambient occlusion.
* @property {number} aoFalloffAngle=0.25 - The falloff angle for the AO calculation.
* @property {number} aoSamplingAmount=0.5 - The fraction of AO samples to use, out of the maximum for each technique.
* @property {number} ssaoNumSpiralTurns=7.0 - The angle span used to distribute the AO samples ray directions. SSAO only.
*/
class AmbientOcclusionPropertyGroup : public PropertyGroup {
public:
// EntityItemProperty related helpers
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
ScriptEngine* engine, bool skipDefaults,
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
bool isMyOwnAvatarEntity) const override;
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
void merge(const AmbientOcclusionPropertyGroup& other);
virtual void debugDump() const override;
virtual void listChangedProperties(QList<QString>& out) override;
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const override;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags,
const unsigned char*& dataAt, int& processedBytes) override;
virtual void markAllChanged() override;
virtual EntityPropertyFlags getChangedProperties() const override;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const override;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const override;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
// FIXME: On some machines, SSAO seems to be causing performance problems. Let's default to HBAO for now and maybe
// revisit when we have Vulkan
DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_OCCLUSION_TECHNIQUE, Technique, technique, AmbientOcclusionTechnique, AmbientOcclusionTechnique::HBAO);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_JITTER, Jitter, jitter, bool, false);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, ResolutionLevel, resolutionLevel, uint8_t, 2);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, EdgeSharpness, edgeSharpness, float, 1.0f);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, BlurRadius, blurRadius, uint8_t, 4);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_RADIUS, AORadius, aoRadius, float, 1.0f);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, AOObscuranceLevel, aoObscuranceLevel, float, 0.5f);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, AOFalloffAngle, aoFalloffAngle, float, 0.25f);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, AOSamplingAmount, aoSamplingAmount, float, 0.5f);
DEFINE_PROPERTY(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, SSAONumSpiralTurns, ssaoNumSpiralTurns, float, 7.0f);
};
#endif // hifi_AmbientOcclusionPropertyGroup_h

View file

@ -48,6 +48,8 @@ BloomPropertyGroup EntityItemProperties::_staticBloom;
ZoneAudioPropertyGroup EntityItemProperties::_staticAudio;
KeyLightPropertyGroup EntityItemProperties::_staticKeyLight;
AmbientLightPropertyGroup EntityItemProperties::_staticAmbientLight;
TonemappingPropertyGroup EntityItemProperties::_staticTonemapping;
AmbientOcclusionPropertyGroup EntityItemProperties::_staticAmbientOcclusion;
GrabPropertyGroup EntityItemProperties::_staticGrab;
PulsePropertyGroup EntityItemProperties::_staticPulse;
RingGizmoPropertyGroup EntityItemProperties::_staticRing;
@ -90,6 +92,8 @@ void EntityItemProperties::debugDump() const {
getAmbientLight().debugDump();
getBloom().debugDump();
getAudio().debugDump();
getTonemapping().debugDump();
getAmbientOcclusion().debugDump();
getGrab().debugDump();
qCDebug(entities) << " changed properties...";
@ -254,6 +258,8 @@ QString EntityItemProperties::getKeyLightModeAsString() const { return getCompon
QString EntityItemProperties::getAmbientLightModeAsString() const { return getComponentModeAsString(_ambientLightMode); }
QString EntityItemProperties::getHazeModeAsString() const { return getComponentModeAsString(_hazeMode); }
QString EntityItemProperties::getBloomModeAsString() const { return getComponentModeAsString(_bloomMode); }
QString EntityItemProperties::getTonemappingModeAsString() const { return getComponentModeAsString(_tonemappingMode); }
QString EntityItemProperties::getAmbientOcclusionModeAsString() const { return getComponentModeAsString(_ambientOcclusionMode); }
void EntityItemProperties::setSkyboxModeFromString(const QString& mode) {
auto modeItr = stringToComponentMode.find(mode.toLower());
if (modeItr != stringToComponentMode.end()) {
@ -289,6 +295,20 @@ void EntityItemProperties::setBloomModeFromString(const QString& mode) {
_bloomModeChanged = true;
}
}
void EntityItemProperties::setTonemappingModeFromString(const QString& mode) {
auto modeItr = stringToComponentMode.find(mode.toLower());
if (modeItr != stringToComponentMode.end()) {
_tonemappingMode = modeItr.value();
_tonemappingModeChanged = true;
}
}
void EntityItemProperties::setAmbientOcclusionModeFromString(const QString& mode) {
auto modeItr = stringToComponentMode.find(mode.toLower());
if (modeItr != stringToComponentMode.end()) {
_ambientOcclusionMode = modeItr.value();
_ambientOcclusionModeChanged = true;
}
}
inline void addAvatarPriorityMode(QHash<QString, AvatarPriorityMode>& lookup, AvatarPriorityMode mode) { lookup[AvatarPriorityModeHelpers::getNameForAvatarPriorityMode(mode)] = mode; }
const QHash<QString, AvatarPriorityMode> stringToAvatarPriority = [] {
@ -625,6 +645,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
changedProperties += _haze.getChangedProperties();
changedProperties += _bloom.getChangedProperties();
changedProperties += _audio.getChangedProperties();
changedProperties += _tonemapping.getChangedProperties();
changedProperties += _ambientOcclusion.getChangedProperties();
CHECK_PROPERTY_CHANGE(PROP_FLYING_ALLOWED, flyingAllowed);
CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
CHECK_PROPERTY_CHANGE(PROP_FILTER_URL, filterURL);
@ -635,6 +657,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_BLOOM_MODE, bloomMode);
CHECK_PROPERTY_CHANGE(PROP_AVATAR_PRIORITY, avatarPriority);
CHECK_PROPERTY_CHANGE(PROP_SCREENSHARE, screenshare);
CHECK_PROPERTY_CHANGE(PROP_TONEMAPPING_MODE, tonemappingMode);
CHECK_PROPERTY_CHANGE(PROP_AMBIENT_OCCLUSION_MODE, ambientOcclusionMode);
// Polyvox
CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize);
@ -1587,6 +1611,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
*
* @property {Entities.ZoneAudio} audio - The audio properties of the zone.
*
* @property {Entities.ComponentMode} tonemappingMode="inherit" - Configures the tonemapping in the zone.
* @property {Entities.Tonemapping} tonemapping - The tonemapping properties of the zone.
*
* @property {Entities.ComponentMode} ambientOcclusionMode="inherit" - Configures the ambient occlusion in the zone.
* @property {Entities.AmbientOcclusion} ambientOcclusion - The ambient occlusion properties of the zone.
*
* @property {boolean} flyingAllowed=true - <code>true</code> if visitors can fly in the zone; <code>false</code> if they
* cannot. Only works for domain entities.
* @property {boolean} ghostingAllowed=true - <code>true</code> if visitors with avatar collisions turned off will not
@ -1951,6 +1981,8 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
_haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
_bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
_audio.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
_tonemapping.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
_ambientOcclusion.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties, returnNothingOnEmptyPropertyFlags, isMyOwnAvatarEntity);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
@ -1963,6 +1995,8 @@ ScriptValue EntityItemProperties::copyToScriptValue(ScriptEngine* engine, bool s
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AVATAR_PRIORITY, avatarPriority, getAvatarPriorityAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SCREENSHARE, screenshare, getScreenshareAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TONEMAPPING_MODE, tonemappingMode, getTonemappingModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_OCCLUSION_MODE, ambientOcclusionMode, getAmbientOcclusionModeAsString());
}
// Web only
@ -2349,6 +2383,8 @@ void EntityItemProperties::copyFromScriptValue(const ScriptValue& object, bool h
_haze.copyFromScriptValue(object, namesSet, _defaultSettings);
_bloom.copyFromScriptValue(object, namesSet, _defaultSettings);
_audio.copyFromScriptValue(object, namesSet, _defaultSettings);
_tonemapping.copyFromScriptValue(object, namesSet, _defaultSettings);
_ambientOcclusion.copyFromScriptValue(object, namesSet, _defaultSettings);
COPY_PROPERTY_FROM_QSCRIPTVALUE(flyingAllowed, bool, setFlyingAllowed);
COPY_PROPERTY_FROM_QSCRIPTVALUE(ghostingAllowed, bool, setGhostingAllowed);
COPY_PROPERTY_FROM_QSCRIPTVALUE(filterURL, QString, setFilterURL);
@ -2359,6 +2395,8 @@ void EntityItemProperties::copyFromScriptValue(const ScriptValue& object, bool h
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(bloomMode, BloomMode);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(avatarPriority, AvatarPriority);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(screenshare, Screenshare);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(tonemappingMode, TonemappingMode);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientOcclusionMode, AmbientOcclusionMode);
// Polyvox
COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, vec3, setVoxelVolumeSize);
@ -2653,6 +2691,8 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
_haze.merge(other._haze);
_bloom.merge(other._bloom);
_audio.merge(other._audio);
_tonemapping.merge(other._tonemapping);
_ambientOcclusion.merge(other._ambientOcclusion);
COPY_PROPERTY_IF_CHANGED(flyingAllowed);
COPY_PROPERTY_IF_CHANGED(ghostingAllowed);
COPY_PROPERTY_IF_CHANGED(filterURL);
@ -2663,6 +2703,8 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
COPY_PROPERTY_IF_CHANGED(bloomMode);
COPY_PROPERTY_IF_CHANGED(avatarPriority);
COPY_PROPERTY_IF_CHANGED(screenshare);
COPY_PROPERTY_IF_CHANGED(tonemappingMode);
COPY_PROPERTY_IF_CHANGED(ambientOcclusionMode);
// Polyvox
COPY_PROPERTY_IF_CHANGED(voxelVolumeSize);
@ -3079,6 +3121,22 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
ADD_GROUP_PROPERTY_TO_MAP(PROP_LISTENER_ZONES, Audio, audio, ListenerZones, listenerZones);
ADD_GROUP_PROPERTY_TO_MAP(PROP_LISTENER_ATTENUATION_COEFFICIENTS, Audio, audio, ListenerAttenuationCoefficients, listenerAttenuationCoefficients);
}
{ // Tonemapping
ADD_GROUP_PROPERTY_TO_MAP(PROP_TONEMAPPING_CURVE, Tonemapping, tonemapping, Curve, curve);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_TONEMAPPING_EXPOSURE, Tonemapping, tonemapping, Exposure, exposure, -4.0f, -4.0f);
}
{ // Ambient Occlusion
ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_OCCLUSION_TECHNIQUE, AmbientOcclusion, ambientOcclusion, Technique, technique);
ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_OCCLUSION_JITTER, AmbientOcclusion, ambientOcclusion, Jitter, jitter);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL, AmbientOcclusion, ambientOcclusion, ResolutionLevel, resolutionLevel, 0, 4);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS, AmbientOcclusion, ambientOcclusion, EdgeSharpness, edgeSharpness, 0.0f, 1.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_BLUR_RADIUS, AmbientOcclusion, ambientOcclusion, BlurRadius, blurRadius, 0, 15);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_AO_RADIUS, AmbientOcclusion, ambientOcclusion, AORadius, aoRadius, 0.01f, 2.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL, AmbientOcclusion, ambientOcclusion, AOObscuranceLevel, aoObscuranceLevel, 0.01f, 1.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE, AmbientOcclusion, ambientOcclusion, AOFalloffAngle, aoFalloffAngle, 0.0f, 1.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT, AmbientOcclusion, ambientOcclusion, AOSamplingAmount, aoSamplingAmount, 0.0f, 1.0f);
ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS, AmbientOcclusion, ambientOcclusion, SSAONumSpiralTurns, ssaoNumSpiralTurns, 0.0f, 10.0f);
}
ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool);
ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool);
ADD_PROPERTY_TO_MAP(PROP_FILTER_URL, FilterURL, filterURL, QString);
@ -3089,6 +3147,8 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
ADD_PROPERTY_TO_MAP(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t);
ADD_PROPERTY_TO_MAP(PROP_AVATAR_PRIORITY, AvatarPriority, avatarPriority, uint32_t);
ADD_PROPERTY_TO_MAP(PROP_SCREENSHARE, Screenshare, screenshare, uint32_t);
ADD_PROPERTY_TO_MAP(PROP_TONEMAPPING_MODE, TonemappingMode, tonemappingMode, uint32_t);
ADD_PROPERTY_TO_MAP(PROP_AMBIENT_OCCLUSION_MODE, AmbientOcclusionMode, ambientOcclusionMode, uint32_t);
// Polyvox
ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, vec3);
@ -3516,6 +3576,12 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
_staticAudio.setProperties(properties);
_staticAudio.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
_staticTonemapping.setProperties(properties);
_staticTonemapping.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
_staticAmbientOcclusion.setProperties(properties);
_staticAmbientOcclusion.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, properties.getFlyingAllowed());
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, properties.getGhostingAllowed());
APPEND_ENTITY_PROPERTY(PROP_FILTER_URL, properties.getFilterURL());
@ -3527,6 +3593,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode());
APPEND_ENTITY_PROPERTY(PROP_AVATAR_PRIORITY, (uint32_t)properties.getAvatarPriority());
APPEND_ENTITY_PROPERTY(PROP_SCREENSHARE, (uint32_t)properties.getScreenshare());
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_MODE, (uint32_t)properties.getTonemappingMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_MODE, (uint32_t)properties.getAmbientOcclusionMode());
}
if (properties.getType() == EntityTypes::PolyVox) {
@ -4006,6 +4074,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getAudio().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getTonemapping().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
properties.getAmbientOcclusion().decodeFromEditPacket(propertyFlags, dataAt, processedBytes);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
@ -4018,6 +4088,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AVATAR_PRIORITY, uint32_t, setAvatarPriority);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCREENSHARE, uint32_t, setScreenshare);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TONEMAPPING_MODE, uint32_t, setTonemappingMode);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AMBIENT_OCCLUSION_MODE, uint32_t, setAmbientOcclusionMode);
}
if (properties.getType() == EntityTypes::PolyVox) {
@ -4399,6 +4471,8 @@ void EntityItemProperties::markAllChanged() {
_haze.markAllChanged();
_bloom.markAllChanged();
_audio.markAllChanged();
_tonemapping.markAllChanged();
_ambientOcclusion.markAllChanged();
_flyingAllowedChanged = true;
_ghostingAllowedChanged = true;
_filterURLChanged = true;
@ -4409,6 +4483,8 @@ void EntityItemProperties::markAllChanged() {
_bloomModeChanged = true;
_avatarPriorityChanged = true;
_screenshareChanged = true;
_tonemappingModeChanged = true;
_ambientOcclusionModeChanged = true;
// Polyvox
_voxelVolumeSizeChanged = true;
@ -5021,6 +5097,8 @@ QList<QString> EntityItemProperties::listChangedProperties() {
getHaze().listChangedProperties(out);
getBloom().listChangedProperties(out);
getAudio().listChangedProperties(out);
getTonemapping().listChangedProperties(out);
getAmbientOcclusion().listChangedProperties(out);
if (flyingAllowedChanged()) {
out += "flyingAllowed";
}
@ -5051,6 +5129,12 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (screenshareChanged()) {
out += "screenshare";
}
if (tonemappingModeChanged()) {
out += "tonemappingMode";
}
if (ambientOcclusionModeChanged()) {
out += "ambientOcclusionMode";
}
// Polyvox
if (voxelVolumeSizeChanged()) {

View file

@ -64,6 +64,8 @@
#include "PulsePropertyGroup.h"
#include "RingGizmoPropertyGroup.h"
#include "ZoneAudioPropertyGroup.h"
#include "TonemappingPropertyGroup.h"
#include "AmbientOcclusionPropertyGroup.h"
#include "MaterialMappingMode.h"
#include "BillboardMode.h"
@ -346,6 +348,8 @@ public:
DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup);
DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup);
DEFINE_PROPERTY_GROUP(Audio, audio, ZoneAudioPropertyGroup);
DEFINE_PROPERTY_GROUP(Tonemapping, tonemapping, TonemappingPropertyGroup);
DEFINE_PROPERTY_GROUP(AmbientOcclusion, ambientOcclusion, AmbientOcclusionPropertyGroup);
DEFINE_PROPERTY(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool, ZoneEntityItem::DEFAULT_FLYING_ALLOWED);
DEFINE_PROPERTY(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool, ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED);
DEFINE_PROPERTY(PROP_FILTER_URL, FilterURL, filterURL, QString, ZoneEntityItem::DEFAULT_FILTER_URL);
@ -356,6 +360,8 @@ public:
DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
DEFINE_PROPERTY_REF_ENUM(PROP_AVATAR_PRIORITY, AvatarPriority, avatarPriority, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
DEFINE_PROPERTY_REF_ENUM(PROP_SCREENSHARE, Screenshare, screenshare, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
DEFINE_PROPERTY_REF_ENUM(PROP_TONEMAPPING_MODE, TonemappingMode, tonemappingMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_OCCLUSION_MODE, AmbientOcclusionMode, ambientOcclusionMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
// Polyvox
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);

View file

@ -175,6 +175,23 @@ enum EntityPropertyList {
PROP_DERIVED_38,
PROP_DERIVED_39,
PROP_DERIVED_40,
PROP_DERIVED_41,
PROP_DERIVED_42,
PROP_DERIVED_43,
PROP_DERIVED_44,
PROP_DERIVED_45,
PROP_DERIVED_46,
PROP_DERIVED_47,
PROP_DERIVED_48,
PROP_DERIVED_49,
PROP_DERIVED_50,
PROP_DERIVED_51,
PROP_DERIVED_52,
PROP_DERIVED_53,
PROP_DERIVED_54,
PROP_DERIVED_55,
PROP_DERIVED_56,
PROP_DERIVED_57,
PROP_AFTER_LAST_ITEM,
@ -276,44 +293,44 @@ enum EntityPropertyList {
// Zone
// Keylight
PROP_KEYLIGHT_COLOR = PROP_DERIVED_0,
PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_1,
PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_2,
PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_3,
PROP_KEYLIGHT_SHADOW_BIAS = PROP_DERIVED_4,
PROP_KEYLIGHT_SHADOW_MAX_DISTANCE = PROP_DERIVED_5,
PROP_KEY_LIGHT_MODE = PROP_DERIVED_0,
PROP_KEYLIGHT_COLOR = PROP_DERIVED_1,
PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_2,
PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_3,
PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_4,
PROP_KEYLIGHT_SHADOW_BIAS = PROP_DERIVED_5,
PROP_KEYLIGHT_SHADOW_MAX_DISTANCE = PROP_DERIVED_6,
// Ambient light
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_6,
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_7,
PROP_AMBIENT_LIGHT_COLOR = PROP_DERIVED_8,
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_7,
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_8,
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_9,
PROP_AMBIENT_LIGHT_COLOR = PROP_DERIVED_10,
// Skybox
PROP_SKYBOX_COLOR = PROP_DERIVED_9,
PROP_SKYBOX_URL = PROP_DERIVED_10,
PROP_SKYBOX_MODE = PROP_DERIVED_11,
PROP_SKYBOX_COLOR = PROP_DERIVED_12,
PROP_SKYBOX_URL = PROP_DERIVED_13,
// Haze
PROP_HAZE_RANGE = PROP_DERIVED_11,
PROP_HAZE_COLOR = PROP_DERIVED_12,
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_13,
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_14,
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_15,
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_16,
PROP_HAZE_CEILING = PROP_DERIVED_17,
PROP_HAZE_BASE_REF = PROP_DERIVED_18,
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_19,
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_20,
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_21,
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_22,
PROP_HAZE_MODE = PROP_DERIVED_14,
PROP_HAZE_RANGE = PROP_DERIVED_15,
PROP_HAZE_COLOR = PROP_DERIVED_16,
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_17,
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_18,
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_19,
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_20,
PROP_HAZE_CEILING = PROP_DERIVED_21,
PROP_HAZE_BASE_REF = PROP_DERIVED_22,
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_23,
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_24,
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_25,
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_26,
// Bloom
PROP_BLOOM_INTENSITY = PROP_DERIVED_23,
PROP_BLOOM_THRESHOLD = PROP_DERIVED_24,
PROP_BLOOM_SIZE = PROP_DERIVED_25,
PROP_FLYING_ALLOWED = PROP_DERIVED_26,
PROP_GHOSTING_ALLOWED = PROP_DERIVED_27,
PROP_FILTER_URL = PROP_DERIVED_28,
PROP_KEY_LIGHT_MODE = PROP_DERIVED_29,
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_30,
PROP_SKYBOX_MODE = PROP_DERIVED_31,
PROP_HAZE_MODE = PROP_DERIVED_32,
PROP_BLOOM_MODE = PROP_DERIVED_33,
PROP_BLOOM_MODE = PROP_DERIVED_27,
PROP_BLOOM_INTENSITY = PROP_DERIVED_28,
PROP_BLOOM_THRESHOLD = PROP_DERIVED_29,
PROP_BLOOM_SIZE = PROP_DERIVED_30,
PROP_FLYING_ALLOWED = PROP_DERIVED_31,
PROP_GHOSTING_ALLOWED = PROP_DERIVED_32,
PROP_FILTER_URL = PROP_DERIVED_33,
// Avatar priority
PROP_AVATAR_PRIORITY = PROP_DERIVED_34,
// Screen-sharing
@ -324,6 +341,22 @@ enum EntityPropertyList {
PROP_REVERB_WET_LEVEL = PROP_DERIVED_38,
PROP_LISTENER_ZONES = PROP_DERIVED_39,
PROP_LISTENER_ATTENUATION_COEFFICIENTS = PROP_DERIVED_40,
// Tonemapping
PROP_TONEMAPPING_MODE = PROP_DERIVED_41,
PROP_TONEMAPPING_CURVE = PROP_DERIVED_42,
PROP_TONEMAPPING_EXPOSURE = PROP_DERIVED_43,
// Ambient Occlusion
PROP_AMBIENT_OCCLUSION_MODE = PROP_DERIVED_44,
PROP_AMBIENT_OCCLUSION_TECHNIQUE = PROP_DERIVED_45,
PROP_AMBIENT_OCCLUSION_JITTER = PROP_DERIVED_46,
PROP_AMBIENT_OCCLUSION_RESOLUTION_LEVEL = PROP_DERIVED_47,
PROP_AMBIENT_OCCLUSION_EDGE_SHARPNESS = PROP_DERIVED_48,
PROP_AMBIENT_OCCLUSION_BLUR_RADIUS = PROP_DERIVED_49,
PROP_AMBIENT_OCCLUSION_AO_RADIUS = PROP_DERIVED_50,
PROP_AMBIENT_OCCLUSION_AO_OBSCURANCE_LEVEL = PROP_DERIVED_51,
PROP_AMBIENT_OCCLUSION_AO_FALLOFF_ANGLE = PROP_DERIVED_52,
PROP_AMBIENT_OCCLUSION_AO_SAMPLING_AMOUNT = PROP_DERIVED_53,
PROP_AMBIENT_OCCLUSION_SSAO_NUM_SPIRAL_TURNS = PROP_DERIVED_54,
// Polyvox
PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0,

View file

@ -0,0 +1,167 @@
//
// TonemappingPropertyGroup.cpp
// libraries/entities/src
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#include "TonemappingPropertyGroup.h"
#include <OctreePacketData.h>
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
inline void addTonemappingCurve(QHash<QString, TonemappingCurve>& lookup, TonemappingCurve curve) { lookup[TonemappingCurveHelpers::getNameForTonemappingCurve(curve)] = curve; }
const QHash<QString, TonemappingCurve> stringToTonemappingCurveLookup = [] {
QHash<QString, TonemappingCurve> toReturn;
addTonemappingCurve(toReturn, TonemappingCurve::RGB);
addTonemappingCurve(toReturn, TonemappingCurve::SRGB);
addTonemappingCurve(toReturn, TonemappingCurve::FILMIC);
addTonemappingCurve(toReturn, TonemappingCurve::REINHARD);
return toReturn;
}();
QString TonemappingPropertyGroup::getCurveAsString() const { return TonemappingCurveHelpers::getNameForTonemappingCurve(_curve); }
void TonemappingPropertyGroup::setCurveFromString(const QString& curve) {
auto curveItr = stringToTonemappingCurveLookup.find(curve.toLower());
if (curveItr != stringToTonemappingCurveLookup.end()) {
_curve = curveItr.value();
_curveChanged = true;
}
}
void TonemappingPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,
bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags, bool isMyOwnAvatarEntity) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_TONEMAPPING_CURVE, Tonemapping, tonemapping, Curve, curve, getCurveAsString);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_TONEMAPPING_EXPOSURE, Tonemapping, tonemapping, Exposure, exposure);
}
void TonemappingPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(tonemapping, curve, Curve);
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(tonemapping, exposure, float, setExposure);
}
void TonemappingPropertyGroup::merge(const TonemappingPropertyGroup& other) {
COPY_PROPERTY_IF_CHANGED(curve);
COPY_PROPERTY_IF_CHANGED(exposure);
}
void TonemappingPropertyGroup::debugDump() const {
qCDebug(entities) << " TonemappingPropertyGroup: ---------------------------------------------";
qCDebug(entities) << " Curve:" << getCurveAsString();
qCDebug(entities) << " Exposure:" << getExposure();
}
void TonemappingPropertyGroup::listChangedProperties(QList<QString>& out) {
if (curveChanged()) {
out << "tonemapping-curve";
}
if (exposureChanged()) {
out << "tonemapping-exposure";
}
}
bool TonemappingPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_CURVE, (uint32_t)getCurve());
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_EXPOSURE, getExposure());
return true;
}
bool TonemappingPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {
int bytesRead = 0;
bool overwriteLocalData = true;
bool somethingChanged = false;
READ_ENTITY_PROPERTY(PROP_TONEMAPPING_CURVE, TonemappingCurve, setCurve);
READ_ENTITY_PROPERTY(PROP_TONEMAPPING_EXPOSURE, float, setExposure);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_TONEMAPPING_CURVE, Curve);
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_TONEMAPPING_EXPOSURE, Exposure);
processedBytes += bytesRead;
Q_UNUSED(somethingChanged);
return true;
}
void TonemappingPropertyGroup::markAllChanged() {
_curveChanged = true;
_exposureChanged = true;
}
EntityPropertyFlags TonemappingPropertyGroup::getChangedProperties() const {
EntityPropertyFlags changedProperties;
CHECK_PROPERTY_CHANGE(PROP_TONEMAPPING_CURVE, curve);
CHECK_PROPERTY_CHANGE(PROP_TONEMAPPING_EXPOSURE, exposure);
return changedProperties;
}
void TonemappingPropertyGroup::getProperties(EntityItemProperties& properties) const {
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Tonemapping, Curve, getCurve);
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Tonemapping, Exposure, getExposure);
}
bool TonemappingPropertyGroup::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Tonemapping, Curve, curve, setCurve);
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Tonemapping, Exposure, exposure, setExposure);
return somethingChanged;
}
EntityPropertyFlags TonemappingPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties;
requestedProperties += PROP_TONEMAPPING_CURVE;
requestedProperties += PROP_TONEMAPPING_EXPOSURE;
return requestedProperties;
}
void TonemappingPropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const {
bool successPropertyFits = true;
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_CURVE, (uint32_t)getCurve());
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_EXPOSURE, getExposure());
}
int TonemappingPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) {
int bytesRead = 0;
const unsigned char* dataAt = data;
READ_ENTITY_PROPERTY(PROP_TONEMAPPING_CURVE, TonemappingCurve, setCurve);
READ_ENTITY_PROPERTY(PROP_TONEMAPPING_EXPOSURE, float, setExposure);
return bytesRead;
}

View file

@ -0,0 +1,87 @@
//
// TonemappingPropertyGroup.h
// libraries/entities/src
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// SPDX-License-Identifier: Apache-2.0
//
#ifndef hifi_TonemappingPropertyGroup_h
#define hifi_TonemappingPropertyGroup_h
#include <TonemappingCurve.h>
#include "PropertyGroup.h"
#include "EntityItemPropertiesMacros.h"
class EntityItemProperties;
class EncodeBitstreamParams;
class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
class ScriptEngine;
class ScriptValue;
/*@jsdoc
* Tonemapping is defined by the following properties:
* @typedef {object} Entities.Tonemapping
* @property {TonemappingCurve} curve="srgb" - The tonemapping curve used.
* @property {number} exposure=0.0 - The applied exposure.
*/
class TonemappingPropertyGroup : public PropertyGroup {
public:
// EntityItemProperty related helpers
virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
ScriptEngine* engine, bool skipDefaults,
EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
bool isMyOwnAvatarEntity) const override;
virtual void copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) override;
void merge(const TonemappingPropertyGroup& other);
virtual void debugDump() const override;
virtual void listChangedProperties(QList<QString>& out) override;
virtual bool appendToEditPacket(OctreePacketData* packetData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const override;
virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags,
const unsigned char*& dataAt, int& processedBytes) override;
virtual void markAllChanged() override;
virtual EntityPropertyFlags getChangedProperties() const override;
// EntityItem related helpers
// methods for getting/setting all properties of an entity
virtual void getProperties(EntityItemProperties& propertiesOut) const override;
/// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit,
int& propertyCount,
OctreeElement::AppendState& appendState) const override;
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
DEFINE_PROPERTY_REF_ENUM(PROP_TONEMAPPING_CURVE, Curve, curve, TonemappingCurve, TonemappingCurve::SRGB);
DEFINE_PROPERTY(PROP_TONEMAPPING_EXPOSURE, Exposure, exposure, float, 0.0);
};
#endif // hifi_TonemappingPropertyGroup_h

View file

@ -61,6 +61,8 @@ EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& de
_hazeProperties.getProperties(properties);
_bloomProperties.getProperties(properties);
_audioProperties.getProperties(properties);
_tonemappingProperties.getProperties(properties);
_ambientOcclusionProperties.getProperties(properties);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed);
@ -73,6 +75,8 @@ EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& de
COPY_ENTITY_PROPERTY_TO_PROPERTIES(bloomMode, getBloomMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(avatarPriority, getAvatarPriority);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(screenshare, getScreenshare);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(tonemappingMode, getTonemappingMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientOcclusionMode, getAmbientOcclusionMode);
return properties;
}
@ -92,6 +96,8 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
_hazePropertiesChanged |= _hazeProperties.setProperties(properties);
_bloomPropertiesChanged |= _bloomProperties.setProperties(properties);
bool audioPropertiesChanged = _audioProperties.setProperties(properties);
_tonemappingPropertiesChanged |= _tonemappingProperties.setProperties(properties);
_ambientOcclusionPropertiesChanged |= _ambientOcclusionProperties.setProperties(properties);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed);
@ -104,9 +110,12 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
SET_ENTITY_PROPERTY_FROM_PROPERTIES(bloomMode, setBloomMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(avatarPriority, setAvatarPriority);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(screenshare, setScreenshare);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(tonemappingMode, setTonemappingMode);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientOcclusionMode, setAmbientOcclusionMode);
somethingChanged |= _keyLightPropertiesChanged || _ambientLightPropertiesChanged || _skyboxPropertiesChanged ||
_hazePropertiesChanged || _bloomPropertiesChanged || audioPropertiesChanged;
_hazePropertiesChanged || _bloomPropertiesChanged || audioPropertiesChanged ||
_tonemappingPropertiesChanged || _ambientOcclusionPropertiesChanged;
return somethingChanged;
}
@ -177,6 +186,20 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
dataAt += bytesFromAudio;
}
{
int bytesFromTonemapping = _tonemappingProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData, somethingChanged);
bytesRead += bytesFromTonemapping;
dataAt += bytesFromTonemapping;
}
{
int bytesFromAmbientOcclusion = _ambientOcclusionProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
propertyFlags, overwriteLocalData, somethingChanged);
bytesRead += bytesFromAmbientOcclusion;
dataAt += bytesFromAmbientOcclusion;
}
READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL);
@ -188,6 +211,8 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
READ_ENTITY_PROPERTY(PROP_BLOOM_MODE, uint32_t, setBloomMode);
READ_ENTITY_PROPERTY(PROP_AVATAR_PRIORITY, uint32_t, setAvatarPriority);
READ_ENTITY_PROPERTY(PROP_SCREENSHARE, uint32_t, setScreenshare);
READ_ENTITY_PROPERTY(PROP_TONEMAPPING_MODE, uint32_t, setTonemappingMode);
READ_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_MODE, uint32_t, setAmbientOcclusionMode);
return bytesRead;
}
@ -204,6 +229,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += _hazeProperties.getEntityProperties(params);
requestedProperties += _bloomProperties.getEntityProperties(params);
requestedProperties += _audioProperties.getEntityProperties(params);
requestedProperties += _tonemappingProperties.getEntityProperties(params);
requestedProperties += _ambientOcclusionProperties.getEntityProperties(params);
requestedProperties += PROP_FLYING_ALLOWED;
requestedProperties += PROP_GHOSTING_ALLOWED;
@ -216,6 +243,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
requestedProperties += PROP_SKYBOX_MODE;
requestedProperties += PROP_HAZE_MODE;
requestedProperties += PROP_BLOOM_MODE;
requestedProperties += PROP_TONEMAPPING_MODE;
requestedProperties += PROP_AMBIENT_OCCLUSION_MODE;
return requestedProperties;
}
@ -247,32 +276,40 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_audioProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_tonemappingProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
_ambientOcclusionProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
propertyFlags, propertiesDidntFit, propertyCount, appendState);
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, getFlyingAllowed());
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, getGhostingAllowed());
APPEND_ENTITY_PROPERTY(PROP_FILTER_URL, getFilterURL());
APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)getKeyLightMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)getAmbientLightMode());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)getSkyboxMode());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, (uint32_t)getHazeMode());
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)getBloomMode());
APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, getKeyLightMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, getAmbientLightMode());
APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, getSkyboxMode());
APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, getHazeMode());
APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, getBloomMode());
APPEND_ENTITY_PROPERTY(PROP_AVATAR_PRIORITY, getAvatarPriority());
APPEND_ENTITY_PROPERTY(PROP_SCREENSHARE, getScreenshare());
APPEND_ENTITY_PROPERTY(PROP_TONEMAPPING_MODE, getTonemappingMode());
APPEND_ENTITY_PROPERTY(PROP_AMBIENT_OCCLUSION_MODE, getAmbientOcclusionMode());
}
void ZoneEntityItem::debugDump() const {
quint64 now = usecTimestampNow();
qCDebug(entities) << " ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------";
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeAsString(_hazeMode);
qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeAsString(_keyLightMode);
qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeAsString(_ambientLightMode);
qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeAsString(_skyboxMode);
qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeAsString(_bloomMode);
qCDebug(entities) << " _avatarPriority:" << getAvatarPriority();
qCDebug(entities) << " ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------";
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeAsString(_hazeMode);
qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeAsString(_keyLightMode);
qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeAsString(_ambientLightMode);
qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeAsString(_skyboxMode);
qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeAsString(_bloomMode);
qCDebug(entities) << " _avatarPriority:" << getAvatarPriority();
qCDebug(entities) << " _tonemappingMode:" << EntityItemProperties::getComponentModeAsString(_tonemappingMode);
qCDebug(entities) << " _ambientOcclusionMode:" << EntityItemProperties::getComponentModeAsString(_ambientOcclusionMode);
_keyLightProperties.debugDump();
_ambientLightProperties.debugDump();
@ -280,6 +317,8 @@ void ZoneEntityItem::debugDump() const {
_hazeProperties.debugDump();
_bloomProperties.debugDump();
_audioProperties.debugDump();
_tonemappingProperties.debugDump();
_ambientOcclusionProperties.debugDump();
}
void ZoneEntityItem::setShapeType(ShapeType type) {
@ -408,53 +447,11 @@ void ZoneEntityItem::resetRenderingPropertiesChanged() {
_skyboxPropertiesChanged = false;
_hazePropertiesChanged = false;
_bloomPropertiesChanged = false;
_tonemappingPropertiesChanged = false;
_ambientOcclusionPropertiesChanged = false;
});
}
void ZoneEntityItem::setHazeMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _hazeMode) {
_hazeMode = value;
_hazePropertiesChanged = true;
}
}
uint32_t ZoneEntityItem::getHazeMode() const {
return _hazeMode;
}
void ZoneEntityItem::setBloomMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _bloomMode) {
_bloomMode = value;
_bloomPropertiesChanged = true;
}
}
uint32_t ZoneEntityItem::getBloomMode() const {
return _bloomMode;
}
void ZoneEntityItem::setKeyLightMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _keyLightMode) {
_keyLightMode = value;
_keyLightPropertiesChanged = true;
}
}
uint32_t ZoneEntityItem::getKeyLightMode() const {
return _keyLightMode;
}
void ZoneEntityItem::setAmbientLightMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _ambientLightMode) {
_ambientLightMode = value;
_ambientLightPropertiesChanged = true;
}
}
uint32_t ZoneEntityItem::getAmbientLightMode() const {
return _ambientLightMode;
}
void ZoneEntityItem::setSkyboxMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _skyboxMode) {
_skyboxMode = value;
@ -462,8 +459,46 @@ void ZoneEntityItem::setSkyboxMode(const uint32_t value) {
}
}
uint32_t ZoneEntityItem::getSkyboxMode() const {
return _skyboxMode;
void ZoneEntityItem::setKeyLightMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _keyLightMode) {
_keyLightMode = value;
_keyLightPropertiesChanged = true;
}
}
void ZoneEntityItem::setAmbientLightMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _ambientLightMode) {
_ambientLightMode = value;
_ambientLightPropertiesChanged = true;
}
}
void ZoneEntityItem::setHazeMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _hazeMode) {
_hazeMode = value;
_hazePropertiesChanged = true;
}
}
void ZoneEntityItem::setBloomMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _bloomMode) {
_bloomMode = value;
_bloomPropertiesChanged = true;
}
}
void ZoneEntityItem::setTonemappingMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _tonemappingMode) {
_tonemappingMode = value;
_tonemappingPropertiesChanged = true;
}
}
void ZoneEntityItem::setAmbientOcclusionMode(const uint32_t value) {
if (value < COMPONENT_MODE_ITEM_COUNT && value != _ambientOcclusionMode) {
_ambientOcclusionMode = value;
_ambientOcclusionPropertiesChanged = true;
}
}
void ZoneEntityItem::setUserData(const QString& value) {

View file

@ -23,6 +23,8 @@
#include "HazePropertyGroup.h"
#include "BloomPropertyGroup.h"
#include "ZoneAudioPropertyGroup.h"
#include "TonemappingPropertyGroup.h"
#include "AmbientOcclusionPropertyGroup.h"
class ZoneEntityItem : public EntityItem {
public:
@ -68,36 +70,20 @@ public:
virtual bool matchesJSONFilters(const QJsonObject& jsonFilters) const override;
KeyLightPropertyGroup getKeyLightProperties() const { return resultWithReadLock<KeyLightPropertyGroup>([&] { return _keyLightProperties; }); }
AmbientLightPropertyGroup getAmbientLightProperties() const { return resultWithReadLock<AmbientLightPropertyGroup>([&] { return _ambientLightProperties; }); }
void setHazeMode(const uint32_t value);
uint32_t getHazeMode() const;
void setSkyboxMode(uint32_t value);
uint32_t getSkyboxMode() const { return _skyboxMode; }
void setKeyLightMode(uint32_t value);
uint32_t getKeyLightMode() const;
uint32_t getKeyLightMode() const { return _keyLightMode; }
void setAmbientLightMode(uint32_t value);
uint32_t getAmbientLightMode() const;
uint32_t getAmbientLightMode() const { return _ambientLightMode; }
void setSkyboxMode(uint32_t value);
uint32_t getSkyboxMode() const;
void setHazeMode(const uint32_t value);
uint32_t getHazeMode() const { return _hazeMode; }
void setBloomMode(const uint32_t value);
uint32_t getBloomMode() const;
SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock<SkyboxPropertyGroup>([&] { return _skyboxProperties; }); }
const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; }
const BloomPropertyGroup& getBloomProperties() const { return _bloomProperties; }
const ZoneAudioPropertyGroup& getAudioProperties() const { return _audioProperties; }
bool getFlyingAllowed() const { return _flyingAllowed; }
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
bool getGhostingAllowed() const { return _ghostingAllowed; }
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
QString getFilterURL() const;
void setFilterURL(const QString url);
uint32_t getBloomMode() const { return _bloomMode; }
uint32_t getAvatarPriority() const { return _avatarPriority; }
void setAvatarPriority(uint32_t value) { _avatarPriority = value; }
@ -105,6 +91,28 @@ public:
uint32_t getScreenshare() const { return _screenshare; }
void setScreenshare(uint32_t value) { _screenshare = value; }
void setTonemappingMode(uint32_t value);
uint32_t getTonemappingMode() const { return _tonemappingMode; }
void setAmbientOcclusionMode(const uint32_t value);
uint32_t getAmbientOcclusionMode() const { return _ambientOcclusionMode; }
SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock<SkyboxPropertyGroup>([&] { return _skyboxProperties; }); }
KeyLightPropertyGroup getKeyLightProperties() const { return resultWithReadLock<KeyLightPropertyGroup>([&] { return _keyLightProperties; }); }
AmbientLightPropertyGroup getAmbientLightProperties() const { return resultWithReadLock<AmbientLightPropertyGroup>([&] { return _ambientLightProperties; }); }
const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; }
const BloomPropertyGroup& getBloomProperties() const { return _bloomProperties; }
const ZoneAudioPropertyGroup& getAudioProperties() const { return _audioProperties; }
const TonemappingPropertyGroup& getTonemappingProperties() const { return _tonemappingProperties; }
const AmbientOcclusionPropertyGroup& getAmbientOcclusionProperties() const { return _ambientOcclusionProperties; }
bool getFlyingAllowed() const { return _flyingAllowed; }
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
bool getGhostingAllowed() const { return _ghostingAllowed; }
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
QString getFilterURL() const;
void setFilterURL(const QString url);
void setUserData(const QString& value) override;
bool keyLightPropertiesChanged() const { return _keyLightPropertiesChanged; }
@ -112,6 +120,8 @@ public:
bool skyboxPropertiesChanged() const { return _skyboxPropertiesChanged; }
bool hazePropertiesChanged() const { return _hazePropertiesChanged; }
bool bloomPropertiesChanged() const { return _bloomPropertiesChanged; }
bool tonemappingPropertiesChanged() const { return _tonemappingPropertiesChanged; }
bool ambientOcclusionPropertiesChanged() const { return _ambientOcclusionPropertiesChanged; }
void resetRenderingPropertiesChanged();
@ -142,35 +152,35 @@ protected:
ShapeType _shapeType { DEFAULT_SHAPE_TYPE };
QString _compoundShapeURL;
// The following 3 values are the defaults for zone creation
uint32_t _keyLightMode { COMPONENT_MODE_INHERIT };
uint32_t _skyboxMode { COMPONENT_MODE_INHERIT };
uint32_t _ambientLightMode { COMPONENT_MODE_INHERIT };
uint32_t _hazeMode { COMPONENT_MODE_INHERIT };
uint32_t _bloomMode { COMPONENT_MODE_INHERIT };
uint32_t _avatarPriority { COMPONENT_MODE_INHERIT };
uint32_t _screenshare { COMPONENT_MODE_INHERIT };
uint32_t _tonemappingMode { COMPONENT_MODE_INHERIT };
uint32_t _ambientOcclusionMode { COMPONENT_MODE_INHERIT };
SkyboxPropertyGroup _skyboxProperties;
HazePropertyGroup _hazeProperties;
BloomPropertyGroup _bloomProperties;
ZoneAudioPropertyGroup _audioProperties;
TonemappingPropertyGroup _tonemappingProperties;
AmbientOcclusionPropertyGroup _ambientOcclusionProperties;
bool _flyingAllowed { DEFAULT_FLYING_ALLOWED };
bool _ghostingAllowed { DEFAULT_GHOSTING_ALLOWED };
QString _filterURL { DEFAULT_FILTER_URL };
// Avatar-updates priority
uint32_t _avatarPriority { COMPONENT_MODE_INHERIT };
// Screen-sharing zone
uint32_t _screenshare { COMPONENT_MODE_INHERIT };
// Dirty flags turn true when either keylight properties is changing values.
bool _keyLightPropertiesChanged { false };
bool _ambientLightPropertiesChanged { false };
bool _skyboxPropertiesChanged { false };
bool _hazePropertiesChanged { false };
bool _bloomPropertiesChanged { false };
bool _tonemappingPropertiesChanged { false };
bool _ambientOcclusionPropertiesChanged { false };
static bool _drawZoneBoundaries;
static bool _zonesArePickable;

View file

@ -0,0 +1,59 @@
//
// AmbientOcclusion.h
// libraries/graphics/src/graphics
//
// Created by HifiExperiments 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_model_AmbientOcclusion_h
#define hifi_model_AmbientOcclusion_h
#include <memory>
#include <AmbientOcclusionTechnique.h>
namespace graphics {
class AmbientOcclusion {
public:
AmbientOcclusion() {}
void setTechnique(const AmbientOcclusionTechnique technique) { _technique = technique; }
void setJitter(const bool jitter) { _jitter = jitter; }
void setResolutionLevel(const uint8_t resolutionLevel) { _resolutionLevel = resolutionLevel; }
void setEdgeSharpness(const float edgeSharpness) { _edgeSharpness = edgeSharpness; }
void setBlurRadius(const uint8_t blurRadius) { _blurRadius = blurRadius; }
void setAORadius(const float aoRadius) { _aoRadius = aoRadius; }
void setAOObscuranceLevel(const float aoObscuranceLevel) { _aoObscuranceLevel = aoObscuranceLevel; }
void setAOFalloffAngle(const float aoFalloffAngle) { _aoFalloffAngle = aoFalloffAngle; }
void setAOSamplingAmount(const float aoSamplingAmount) { _aoSamplingAmount = aoSamplingAmount; }
void setSSAONumSpiralTurns(const float ssaoNumSpiralTurns) { _ssaoNumSpiralTurns = ssaoNumSpiralTurns; }
AmbientOcclusionTechnique getTechnique() const { return _technique; }
bool getJitter() const { return _jitter; }
uint8_t getResolutionLevel() const { return _resolutionLevel; }
float getEdgeSharpness() const { return _edgeSharpness; }
uint8_t getBlurRadius() const { return _blurRadius; }
float getAORadius() const { return _aoRadius; }
float getAOObscuranceLevel() const { return _aoObscuranceLevel; }
float getAOFalloffAngle() const { return _aoFalloffAngle; }
float getAOSamplingAmount() const { return _aoSamplingAmount; }
float getSSAONumSpiralTurns() const { return _ssaoNumSpiralTurns; }
private:
AmbientOcclusionTechnique _technique { AmbientOcclusionTechnique::SSAO };
bool _jitter { false };
uint8_t _resolutionLevel { 2 };
float _edgeSharpness { 1.0f };
uint8_t _blurRadius { 4 };
float _aoRadius { 1.0f };
float _aoObscuranceLevel { 0.5f };
float _aoFalloffAngle { 0.25f };
float _aoSamplingAmount { 0.5f };
float _ssaoNumSpiralTurns { 7.0f };
};
using AmbientOcclusionPointer = std::shared_ptr<AmbientOcclusion>;
}
#endif // hifi_model_AmbientOcclusion_h

View file

@ -0,0 +1,35 @@
//
// Tonemapping.h
// libraries/graphics/src/graphics
//
// Created by HifiExperiments on 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_model_Tonemapping_h
#define hifi_model_Tonemapping_h
#include <memory>
#include <TonemappingCurve.h>
namespace graphics {
class Tonemapping {
public:
Tonemapping() {}
void setCurve(const TonemappingCurve curve) { _curve = curve; }
void setExposure(const float exposure) { _exposure = exposure; }
TonemappingCurve getCurve() const { return _curve; }
float getExposure() const { return _exposure; }
private:
TonemappingCurve _curve { TonemappingCurve::SRGB };
float _exposure { 0.0f };
};
using TonemappingPointer = std::shared_ptr<Tonemapping>;
}
#endif // hifi_model_Tonemapping_h

View file

@ -299,6 +299,7 @@ enum class EntityVersion : PacketVersion {
ShapeUnlit,
AmbientColor,
SoundEntities,
TonemappingAndAmbientOcclusion,
// Add new versions above here
NUM_PACKET_TYPE,

View file

@ -43,6 +43,8 @@
#include "TextEffect.h"
#include "TextAlignment.h"
#include "MirrorMode.h"
#include "TonemappingCurve.h"
#include "AmbientOcclusionTechnique.h"
#include "OctreeConstants.h"
#include "OctreeElement.h"
@ -285,6 +287,8 @@ public:
static int unpackDataFromBytes(const unsigned char* dataBytes, TextEffect& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, TextAlignment& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, MirrorMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, TonemappingCurve& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, AmbientOcclusionTechnique& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); }
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result);

View file

@ -37,6 +37,9 @@ gpu::PipelinePointer AmbientOcclusionEffect::_mipCreationPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_gatherPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_buildNormalsPipeline;
#define MAX_SSAO_SAMPLES 64.0f
#define MAX_HBAO_SAMPLES 6.0f
AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() {
}
@ -205,29 +208,7 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
}
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion"),
perspectiveScale{ 1.0f },
edgeSharpness{ 1.0f },
blurRadius{ 4 },
resolutionLevel{ 2 },
ssaoRadius{ 1.0f },
ssaoObscuranceLevel{ 0.4f },
ssaoFalloffAngle{ 0.15f },
ssaoNumSpiralTurns{ 7.0f },
ssaoNumSamples{ 32 },
hbaoRadius{ 0.7f },
hbaoObscuranceLevel{ 0.75f },
hbaoFalloffAngle{ 0.3f },
hbaoNumSamples{ 1 },
horizonBased{ false },
ditheringEnabled{ true },
borderingEnabled{ true },
fetchMipsEnabled{ true },
jitterEnabled{ false }{
}
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion") {}
void AmbientOcclusionEffectConfig::setSSAORadius(float newRadius) {
ssaoRadius = std::max(0.01f, newRadius); emit dirty();
@ -288,89 +269,105 @@ void AmbientOcclusionEffectConfig::setBlurRadius(int radius) {
}
AmbientOcclusionEffect::AOParameters::AOParameters() {
_resolutionInfo = glm::vec4{ 0.0f };
_radiusInfo = glm::vec4{ 0.0f };
_ditheringInfo = glm::vec4{ 0.0f };
_sampleInfo = glm::vec4{ 0.0f };
_falloffInfo = glm::vec4{ 0.0f };
_resolutionInfo = glm::vec4(0.0f);
_radiusInfo = glm::vec4(0.0f);
_ditheringInfo = glm::vec4(0.0f);
_sampleInfo = glm::vec4(0.0f);
_falloffInfo = glm::vec4(0.0f);
}
AmbientOcclusionEffect::BlurParameters::BlurParameters() {
_blurInfo = { 1.0f, 2.0f, 0.0f, 3.0f };
}
AmbientOcclusionEffect::AmbientOcclusionEffect() {
void AmbientOcclusionEffect::configure(const Config& config) {
_debug = config.debug;
_debugAmbientOcclusion->setTechnique(config.horizonBased ? AmbientOcclusionTechnique::HBAO : AmbientOcclusionTechnique::SSAO);
_debugAmbientOcclusion->setJitter(config.jitterEnabled);
_debugAmbientOcclusion->setResolutionLevel(config.resolutionLevel);
_debugAmbientOcclusion->setEdgeSharpness(config.edgeSharpness);
_debugAmbientOcclusion->setBlurRadius(config.blurRadius);
_debugAmbientOcclusion->setAORadius(config.horizonBased ? config.hbaoRadius : config.ssaoRadius);
_debugAmbientOcclusion->setAOObscuranceLevel(config.horizonBased ? config.hbaoObscuranceLevel : config.ssaoObscuranceLevel);
_debugAmbientOcclusion->setAOFalloffAngle(config.horizonBased ? config.hbaoFalloffAngle : config.ssaoFalloffAngle);
_debugAmbientOcclusion->setAOSamplingAmount(config.horizonBased ? (config.hbaoNumSamples / MAX_HBAO_SAMPLES) :
(config.ssaoNumSamples / MAX_SSAO_SAMPLES));
_debugAmbientOcclusion->setSSAONumSpiralTurns(config.ssaoNumSpiralTurns);
_perspectiveScale = config.perspectiveScale;
_ditheringEnabled = config.ditheringEnabled;
_borderingEnabled = config.borderingEnabled;
_fetchMipsEnabled = config.fetchMipsEnabled;
}
void AmbientOcclusionEffect::configure(const Config& config) {
void AmbientOcclusionEffect::updateParameters(const graphics::AmbientOcclusionPointer ambientOcclusion) {
bool shouldUpdateBlurs = false;
bool shouldUpdateTechnique = false;
_isJitterEnabled = config.jitterEnabled;
if (!_framebuffer) {
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
shouldUpdateBlurs = true;
}
// Update bilateral blur
if (config.blurRadius != _hblurParametersBuffer->getBlurRadius() || _blurEdgeSharpness != config.edgeSharpness) {
if (ambientOcclusion->getBlurRadius() != _hblurParametersBuffer->getBlurRadius() || _blurEdgeSharpness != ambientOcclusion->getEdgeSharpness()) {
const float BLUR_EDGE_DISTANCE_SCALE = float(10000 * SSAO_DEPTH_KEY_SCALE);
const float BLUR_EDGE_NORMAL_SCALE = 2.0f;
auto& hblur = _hblurParametersBuffer.edit()._blurInfo;
auto& vblur = _vblurParametersBuffer.edit()._blurInfo;
float blurRadialSigma = float(config.blurRadius) * 0.5f;
float blurRadialSigma = float(ambientOcclusion->getBlurRadius()) * 0.5f;
float blurRadialScale = 1.0f / (2.0f*blurRadialSigma*blurRadialSigma);
glm::vec3 blurScales = -glm::vec3(blurRadialScale, glm::vec2(BLUR_EDGE_DISTANCE_SCALE, BLUR_EDGE_NORMAL_SCALE) * config.edgeSharpness);
glm::vec3 blurScales = -glm::vec3(blurRadialScale, glm::vec2(BLUR_EDGE_DISTANCE_SCALE, BLUR_EDGE_NORMAL_SCALE) * ambientOcclusion->getEdgeSharpness());
_blurEdgeSharpness = config.edgeSharpness;
_blurEdgeSharpness = ambientOcclusion->getEdgeSharpness();
hblur.x = blurScales.x;
hblur.y = blurScales.y;
hblur.z = blurScales.z;
hblur.w = (float)config.blurRadius;
hblur.w = (float)ambientOcclusion->getBlurRadius();
vblur.x = blurScales.x;
vblur.y = blurScales.y;
vblur.z = blurScales.z;
vblur.w = (float)config.blurRadius;
vblur.w = (float)ambientOcclusion->getBlurRadius();
}
if (_aoParametersBuffer->isHorizonBased() != config.horizonBased) {
if (_perspectiveScale != _aoParametersBuffer->getPerspectiveScale()) {
_aoParametersBuffer.edit()._resolutionInfo.z = _perspectiveScale;
}
if (_ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
auto& current = _aoParametersBuffer.edit()._ditheringInfo;
current.x = (float)_ditheringEnabled;
}
if (_borderingEnabled != _aoParametersBuffer->isBorderingEnabled()) {
auto& current = _aoParametersBuffer.edit()._ditheringInfo;
current.w = (float)_borderingEnabled;
}
if (_fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) {
auto& current = _aoParametersBuffer.edit()._sampleInfo;
current.w = (float)_fetchMipsEnabled;
}
bool horizonBased = ambientOcclusion->getTechnique() == AmbientOcclusionTechnique::HBAO;
if (_aoParametersBuffer->isHorizonBased() != horizonBased) {
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
current.y = config.horizonBased & 1;
current.y = horizonBased & 1;
shouldUpdateTechnique = true;
}
if (config.fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) {
auto& current = _aoParametersBuffer.edit()._sampleInfo;
current.w = (float)config.fetchMipsEnabled;
}
if (config.perspectiveScale != _aoParametersBuffer->getPerspectiveScale()) {
_aoParametersBuffer.edit()._resolutionInfo.z = config.perspectiveScale;
}
if (config.resolutionLevel != _aoParametersBuffer->getResolutionLevel()) {
if (ambientOcclusion->getResolutionLevel() != _aoParametersBuffer->getResolutionLevel()) {
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
current.x = (float)config.resolutionLevel;
current.x = (float)ambientOcclusion->getResolutionLevel();
shouldUpdateBlurs = true;
}
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
auto& current = _aoParametersBuffer.edit()._ditheringInfo;
current.x = (float)config.ditheringEnabled;
}
if (config.borderingEnabled != _aoParametersBuffer->isBorderingEnabled()) {
auto& current = _aoParametersBuffer.edit()._ditheringInfo;
current.w = (float)config.borderingEnabled;
}
if (config.horizonBased) {
if (horizonBased) {
// Configure for HBAO
const auto& radius = config.hbaoRadius;
const auto& radius = ambientOcclusion->getAORadius();
if (shouldUpdateTechnique || radius != _aoParametersBuffer->getRadius()) {
auto& current = _aoParametersBuffer.edit()._radiusInfo;
current.x = radius;
@ -378,31 +375,33 @@ void AmbientOcclusionEffect::configure(const Config& config) {
current.z = 1.0f / current.y;
}
if (shouldUpdateTechnique || config.hbaoObscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
if (shouldUpdateTechnique || ambientOcclusion->getAOObscuranceLevel() != _aoParametersBuffer->getObscuranceLevel()) {
auto& current = _aoParametersBuffer.edit()._radiusInfo;
current.w = config.hbaoObscuranceLevel;
current.w = ambientOcclusion->getAOObscuranceLevel();
}
if (shouldUpdateTechnique || config.hbaoFalloffAngle != _aoParametersBuffer->getFalloffAngle()) {
const float falloffAngle = std::min(1.0f - EPSILON, ambientOcclusion->getAOFalloffAngle());
if (shouldUpdateTechnique || falloffAngle != _aoParametersBuffer->getFalloffAngle()) {
auto& current = _aoParametersBuffer.edit()._falloffInfo;
current.x = config.hbaoFalloffAngle;
current.x = falloffAngle;
current.y = 1.0f / (1.0f - current.x);
// Compute sin from cos
current.z = sqrtf(1.0f - config.hbaoFalloffAngle * config.hbaoFalloffAngle);
current.z = sqrtf(1.0f - current.x * current.x);
current.w = 1.0f / current.z;
}
if (shouldUpdateTechnique || config.hbaoNumSamples != _aoParametersBuffer->getNumSamples()) {
const int numSamples = std::max(1, (int)(ambientOcclusion->getAOSamplingAmount() * MAX_HBAO_SAMPLES));
if (shouldUpdateTechnique || numSamples != _aoParametersBuffer->getNumSamples()) {
auto& current = _aoParametersBuffer.edit()._sampleInfo;
current.x = config.hbaoNumSamples;
current.y = 1.0f / config.hbaoNumSamples;
current.x = numSamples;
current.y = 1.0f / numSamples;
updateRandomSamples();
updateJitterSamples();
}
} else {
// Configure for SSAO
const double RADIUS_POWER = 6.0;
const auto& radius = config.ssaoRadius;
const auto& radius = ambientOcclusion->getAORadius();
if (shouldUpdateTechnique || radius != _aoParametersBuffer->getRadius()) {
auto& current = _aoParametersBuffer.edit()._radiusInfo;
current.x = radius;
@ -410,25 +409,26 @@ void AmbientOcclusionEffect::configure(const Config& config) {
current.z = (float)(10.0 / pow((double)radius, RADIUS_POWER));
}
if (shouldUpdateTechnique || config.ssaoObscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
if (shouldUpdateTechnique || ambientOcclusion->getAOObscuranceLevel() != _aoParametersBuffer->getObscuranceLevel()) {
auto& current = _aoParametersBuffer.edit()._radiusInfo;
current.w = config.ssaoObscuranceLevel;
current.w = ambientOcclusion->getAOObscuranceLevel();
}
if (shouldUpdateTechnique || config.ssaoFalloffAngle != _aoParametersBuffer->getFalloffAngle()) {
if (shouldUpdateTechnique || ambientOcclusion->getAOFalloffAngle() != _aoParametersBuffer->getFalloffAngle()) {
auto& current = _aoParametersBuffer.edit()._falloffInfo;
current.x = config.ssaoFalloffAngle;
current.x = ambientOcclusion->getAOFalloffAngle();
}
if (shouldUpdateTechnique || config.ssaoNumSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
if (shouldUpdateTechnique || ambientOcclusion->getSSAONumSpiralTurns() != _aoParametersBuffer->getNumSpiralTurns()) {
auto& current = _aoParametersBuffer.edit()._sampleInfo;
current.z = config.ssaoNumSpiralTurns;
current.z = ambientOcclusion->getSSAONumSpiralTurns();
}
if (shouldUpdateTechnique || config.ssaoNumSamples != _aoParametersBuffer->getNumSamples()) {
const int numSamples = std::max(1, (int)(ambientOcclusion->getAOSamplingAmount() * MAX_SSAO_SAMPLES));
if (shouldUpdateTechnique || numSamples != _aoParametersBuffer->getNumSamples()) {
auto& current = _aoParametersBuffer.edit()._sampleInfo;
current.x = config.ssaoNumSamples;
current.y = 1.0f / config.ssaoNumSamples;
current.x = numSamples;
current.y = 1.0f / numSamples;
updateRandomSamples();
updateJitterSamples();
}
@ -600,12 +600,23 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
RenderArgs* args = renderContext->args;
const auto& lightingModel = input.get0();
const auto ambientOcclusionFrame = input.get4();
if (!lightingModel->isAmbientOcclusionEnabled()) {
const auto& ambientOcclusionStage = renderContext->_scene->getStage<AmbientOcclusionStage>();
graphics::AmbientOcclusionPointer ambientOcclusion;
if (_debug) {
ambientOcclusion = _debugAmbientOcclusion;
} else if (ambientOcclusionStage && ambientOcclusionFrame->_ambientOcclusions.size()) {
ambientOcclusion = ambientOcclusionStage->getAmbientOcclusion(ambientOcclusionFrame->_ambientOcclusions.front());
}
if (!ambientOcclusion || !lightingModel->isAmbientOcclusionEnabled()) {
output.edit0().reset();
return;
}
updateParameters(ambientOcclusion);
const auto& frameTransform = input.get1();
const auto& linearDepthFramebuffer = input.get3();
@ -657,7 +668,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
#endif
// Update sample rotation
if (_isJitterEnabled) {
if (ambientOcclusion->getJitter()) {
updateJitterSamples();
_frameId = (_frameId + 1) % (SSAO_RANDOM_SAMPLE_COUNT);
}
@ -831,11 +842,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage());
}
DebugAmbientOcclusion::DebugAmbientOcclusion() {
}
void DebugAmbientOcclusion::configure(const Config& config) {
_showCursorPixel = config.showCursorPixel;
auto cursorPos = glm::vec2(_parametersBuffer->pixelInfo);
@ -916,9 +923,6 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, nullptr);
});
}

View file

@ -21,6 +21,7 @@
#include "DeferredFrameTransform.h"
#include "DeferredFramebuffer.h"
#include "SurfaceGeometryPass.h"
#include "AmbientOcclusionStage.h"
#include "ssao_shared.h"
@ -70,15 +71,16 @@ protected:
#endif
glm::ivec2 _frameSize;
int _resolutionLevel{ 0 };
int _depthResolutionLevel{ 0 };
bool _isStereo{ false };
int _resolutionLevel { 0 };
int _depthResolutionLevel { 0 };
bool _isStereo { false };
};
using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFramebuffer>;
class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
Q_OBJECT
Q_PROPERTY(bool debug MEMBER debug NOTIFY dirty)
Q_PROPERTY(bool horizonBased MEMBER horizonBased NOTIFY dirty)
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
@ -108,42 +110,44 @@ public:
const int MAX_RESOLUTION_LEVEL = 4;
const int MAX_BLUR_RADIUS = 15;
void setEdgeSharpness(float sharpness);
void setResolutionLevel(int level);
void setEdgeSharpness(float sharpness);
void setBlurRadius(int radius);
void setSSAORadius(float newRadius);
void setSSAOObscuranceLevel(float level);
void setSSAOFalloffAngle(float bias);
void setSSAONumSpiralTurns(float turns);
void setSSAONumSamples(int samples);
void setSSAONumSpiralTurns(float turns);
void setHBAORadius(float newRadius);
void setHBAOObscuranceLevel(float level);
void setHBAOFalloffAngle(float bias);
void setHBAONumSamples(int samples);
float perspectiveScale;
float edgeSharpness;
int blurRadius; // 0 means no blurring
int resolutionLevel;
bool debug { false };
float ssaoRadius;
float ssaoObscuranceLevel; // intensify or dim down the obscurance effect
float ssaoFalloffAngle;
float ssaoNumSpiralTurns; // defining an angle span to distribute the samples ray directions
int ssaoNumSamples;
bool jitterEnabled { false }; // Add small jittering to AO samples at each frame
bool horizonBased { false }; // Use horizon based AO
int resolutionLevel { 2 };
float edgeSharpness { 1.0f };
int blurRadius { 4 }; // 0 means no blurring
float hbaoRadius;
float hbaoObscuranceLevel; // intensify or dim down the obscurance effect
float hbaoFalloffAngle;
int hbaoNumSamples;
float ssaoRadius { 1.0f };
float ssaoObscuranceLevel { 0.4f }; // intensify or dim down the obscurance effect
float ssaoFalloffAngle { 0.15f };
int ssaoNumSamples { 32 };
float ssaoNumSpiralTurns { 7.0f }; // defining an angle span to distribute the samples ray directions
bool horizonBased; // Use horizon based AO
bool ditheringEnabled; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled; // fetch taps in sub mips to otpimize cache, should always be true
bool jitterEnabled; // Add small jittering to AO samples at each frame
float hbaoRadius { 0.7f };
float hbaoObscuranceLevel { 0.75f }; // intensify or dim down the obscurance effect
float hbaoFalloffAngle { 0.3f };
int hbaoNumSamples { 1 };
float perspectiveScale { 1.0f };
bool ditheringEnabled { true }; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled { true }; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled { true }; // fetch taps in sub mips to otpimize cache, should always be true
signals:
void dirty();
@ -153,12 +157,13 @@ signals:
class AmbientOcclusionEffect {
public:
using Input = render::VaryingSet4<LightingModelPointer, DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
using Input = render::VaryingSet5<LightingModelPointer, DeferredFrameTransformPointer, DeferredFramebufferPointer,
LinearDepthFramebufferPointer, AmbientOcclusionStage::FramePointer>;
using Output = render::VaryingSet2<AmbientOcclusionFramebufferPointer, gpu::BufferView>;
using Config = AmbientOcclusionEffectConfig;
using JobModel = render::Job::ModelIO<AmbientOcclusionEffect, Input, Output, Config>;
AmbientOcclusionEffect();
AmbientOcclusionEffect() {}
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
@ -166,7 +171,6 @@ public:
// Class describing the uniform buffer with all the parameters common to the AO shaders
class AOParameters : public AmbientOcclusionParams {
public:
AOParameters();
int getResolutionLevel() const { return _resolutionInfo.x; }
@ -182,7 +186,6 @@ public:
bool isDitheringEnabled() const { return _ditheringInfo.x != 0.0f; }
bool isBorderingEnabled() const { return _ditheringInfo.w != 0.0f; }
bool isHorizonBased() const { return _resolutionInfo.y != 0.0f; }
};
using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
@ -191,17 +194,15 @@ private:
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
class BlurParameters : public AmbientOcclusionBlurParams {
public:
BlurParameters();
float getEdgeSharpness() const { return (float)_blurInfo.x; }
int getBlurRadius() const { return (int)_blurInfo.w; }
};
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
using FrameParametersBuffer = gpu::StructBuffer< AmbientOcclusionFrameParams>;
void updateParameters(const graphics::AmbientOcclusionPointer ambientOcclusion);
void updateBlurParameters();
void updateFramebufferSizes();
void updateRandomSamples();
@ -213,7 +214,7 @@ private:
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
BlurParametersBuffer _vblurParametersBuffer;
BlurParametersBuffer _hblurParametersBuffer;
float _blurEdgeSharpness{ 0.0f };
float _blurEdgeSharpness { 0.0f };
static const gpu::PipelinePointer& getOcclusionPipeline();
static const gpu::PipelinePointer& getBilateralBlurPipeline();
@ -229,9 +230,14 @@ private:
AmbientOcclusionFramebufferPointer _framebuffer;
std::array<float, SSAO_RANDOM_SAMPLE_COUNT * SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT> _randomSamples;
int _frameId{ 0 };
bool _isJitterEnabled{ true };
int _frameId { 0 };
bool _debug { false };
float _perspectiveScale { 1.0f };
bool _ditheringEnabled { true };
bool _borderingEnabled { true };
bool _fetchMipsEnabled { true };
graphics::AmbientOcclusionPointer _debugAmbientOcclusion { std::make_shared<graphics::AmbientOcclusion>() };
gpu::RangeTimerPointer _gpuTimer;
friend class DebugAmbientOcclusion;
@ -246,8 +252,8 @@ class DebugAmbientOcclusionConfig : public render::Job::Config {
public:
DebugAmbientOcclusionConfig() : render::Job::Config(false) {}
bool showCursorPixel{ false };
glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f };
bool showCursorPixel { false };
glm::vec2 debugCursorTexcoord { 0.5f, 0.5f };
signals:
void dirty();
@ -260,7 +266,7 @@ public:
using Config = DebugAmbientOcclusionConfig;
using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;
DebugAmbientOcclusion();
DebugAmbientOcclusion() {}
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
@ -281,7 +287,7 @@ private:
gpu::PipelinePointer _debugPipeline;
bool _showCursorPixel{ false };
bool _showCursorPixel { false };
};
#endif // hifi_AmbientOcclusionEffect_h

View file

@ -0,0 +1,56 @@
//
// AmbientOcclusionStage.cpp
//
// Created by HifiExperiments on 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AmbientOcclusionStage.h"
#include <gpu/Context.h>
std::string AmbientOcclusionStage::_stageName { "AMBIENT_OCCLUSION_STAGE" };
const AmbientOcclusionStage::Index AmbientOcclusionStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
AmbientOcclusionStage::Index AmbientOcclusionStage::findAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) const {
auto found = _ambientOcclusionMap.find(ambientOcclusion);
if (found != _ambientOcclusionMap.end()) {
return INVALID_INDEX;
} else {
return (*found).second;
}
}
AmbientOcclusionStage::Index AmbientOcclusionStage::addAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) {
auto found = _ambientOcclusionMap.find(ambientOcclusion);
if (found == _ambientOcclusionMap.end()) {
auto ambientOcclusionId = _ambientOcclusions.newElement(ambientOcclusion);
// Avoid failing to allocate a ambientOcclusion, just pass
if (ambientOcclusionId != INVALID_INDEX) {
// Insert the ambientOcclusion and its index in the reverse map
_ambientOcclusionMap.insert(AmbientOcclusionMap::value_type(ambientOcclusion, ambientOcclusionId));
}
return ambientOcclusionId;
} else {
return (*found).second;
}
}
AmbientOcclusionStage::AmbientOcclusionPointer AmbientOcclusionStage::removeAmbientOcclusion(Index index) {
AmbientOcclusionPointer removed = _ambientOcclusions.freeElement(index);
if (removed) {
_ambientOcclusionMap.erase(removed);
}
return removed;
}
AmbientOcclusionStageSetup::AmbientOcclusionStageSetup() {}
void AmbientOcclusionStageSetup::run(const render::RenderContextPointer& renderContext) {
auto stage = renderContext->_scene->getStage(AmbientOcclusionStage::getName());
if (!stage) {
renderContext->_scene->resetStage(AmbientOcclusionStage::getName(), std::make_shared<AmbientOcclusionStage>());
}
}

View file

@ -0,0 +1,84 @@
//
// AmbientOcclusionStage.h
//
// Created by HifiExperiments on 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_render_utils_AmbientOcclusionStage_h
#define hifi_render_utils_AmbientOcclusionStage_h
#include <graphics/Stage.h>
#include <set>
#include <unordered_map>
#include <render/IndexedContainer.h>
#include <render/Stage.h>
#include <render/Forward.h>
#include <render/DrawTask.h>
#include <graphics/AmbientOcclusion.h>
// AmbientOcclusion stage to set up ambientOcclusion-related rendering tasks
class AmbientOcclusionStage : public render::Stage {
public:
static std::string _stageName;
static const std::string& getName() { return _stageName; }
using Index = render::indexed_container::Index;
static const Index INVALID_INDEX;
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
using AmbientOcclusionPointer = graphics::AmbientOcclusionPointer;
using AmbientOcclusions = render::indexed_container::IndexedPointerVector<graphics::AmbientOcclusion>;
using AmbientOcclusionMap = std::unordered_map<AmbientOcclusionPointer, Index>;
using AmbientOcclusionIndices = std::vector<Index>;
Index findAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion) const;
Index addAmbientOcclusion(const AmbientOcclusionPointer& ambientOcclusion);
AmbientOcclusionPointer removeAmbientOcclusion(Index index);
bool checkAmbientOcclusionId(Index index) const { return _ambientOcclusions.checkIndex(index); }
Index getNumAmbientOcclusions() const { return _ambientOcclusions.getNumElements(); }
Index getNumFreeAmbientOcclusions() const { return _ambientOcclusions.getNumFreeIndices(); }
Index getNumAllocatedAmbientOcclusions() const { return _ambientOcclusions.getNumAllocatedIndices(); }
AmbientOcclusionPointer getAmbientOcclusion(Index ambientOcclusionId) const {
return _ambientOcclusions.get(ambientOcclusionId);
}
AmbientOcclusions _ambientOcclusions;
AmbientOcclusionMap _ambientOcclusionMap;
class Frame {
public:
Frame() {}
void clear() { _ambientOcclusions.clear(); }
void pushAmbientOcclusion(AmbientOcclusionStage::Index index) { _ambientOcclusions.emplace_back(index); }
AmbientOcclusionStage::AmbientOcclusionIndices _ambientOcclusions;
};
using FramePointer = std::shared_ptr<Frame>;
Frame _currentFrame;
};
using AmbientOcclusionStagePointer = std::shared_ptr<AmbientOcclusionStage>;
class AmbientOcclusionStageSetup {
public:
using JobModel = render::Job::Model<AmbientOcclusionStageSetup>;
AmbientOcclusionStageSetup();
void run(const render::RenderContextPointer& renderContext);
protected:
};
#endif

View file

@ -25,6 +25,14 @@ void FetchCurrentFrames::run(const render::RenderContextPointer& renderContext,
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
assert(bloomStage);
output.edit3() = std::make_shared<BloomStage::Frame>(bloomStage->_currentFrame);
auto tonemappingStage = renderContext->_scene->getStage<TonemappingStage>();
assert(tonemappingStage);
output.edit4() = std::make_shared<TonemappingStage::Frame>(tonemappingStage->_currentFrame);
auto ambientOcclusionStage = renderContext->_scene->getStage<AmbientOcclusionStage>();
assert(ambientOcclusionStage);
output.edit5() = std::make_shared<AmbientOcclusionStage::Frame>(ambientOcclusionStage->_currentFrame);
}
@ -47,4 +55,3 @@ void AssembleLightingStageTask::build(JobModel& task, const render::Varying& inp
output = Output(currentStageFrames, zones);
}

View file

@ -16,13 +16,16 @@
#include "BackgroundStage.h"
#include "HazeStage.h"
#include "BloomStage.h"
#include "TonemappingStage.h"
#include "AmbientOcclusionStage.h"
#include "ZoneRenderer.h"
class FetchCurrentFrames {
public:
using Output = render::VaryingSet4<LightStage::FramePointer, BackgroundStage::FramePointer, HazeStage::FramePointer, BloomStage::FramePointer>;
using Output = render::VaryingSet6<LightStage::FramePointer, BackgroundStage::FramePointer, HazeStage::FramePointer,
BloomStage::FramePointer, TonemappingStage::FramePointer, AmbientOcclusionStage::FramePointer>;
using JobModel = render::Job::ModelO<FetchCurrentFrames, Output>;
FetchCurrentFrames() {}

View file

@ -15,7 +15,7 @@
#include <graphics/ShaderConstants.h>
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"};
std::string BackgroundStage::_stageName { "BACKGROUND_STAGE" };
const BackgroundStage::Index BackgroundStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const {

View file

@ -13,7 +13,7 @@
#include <gpu/Context.h>
std::string BloomStage::_stageName { "BLOOM_STAGE"};
std::string BloomStage::_stageName { "BLOOM_STAGE" };
const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const {

View file

@ -81,26 +81,4 @@ public:
protected:
};
class FetchBloomConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float bloomIntensity MEMBER bloomIntensity WRITE setBloomIntensity NOTIFY dirty);
Q_PROPERTY(float bloomThreshold MEMBER bloomThreshold WRITE setBloomThreshold NOTIFY dirty);
Q_PROPERTY(float bloomSize MEMBER bloomSize WRITE setBloomSize NOTIFY dirty);
public:
FetchBloomConfig() : render::Job::Config() {}
float bloomIntensity { graphics::Bloom::INITIAL_BLOOM_INTENSITY };
float bloomThreshold { graphics::Bloom::INITIAL_BLOOM_THRESHOLD };
float bloomSize { graphics::Bloom::INITIAL_BLOOM_SIZE };
public slots:
void setBloomIntensity(const float value) { bloomIntensity = value; emit dirty(); }
void setBloomThreshold(const float value) { bloomThreshold = value; emit dirty(); }
void setBloomSize(const float value) { bloomSize = value; emit dirty(); }
signals:
void dirty();
};
#endif

View file

@ -662,5 +662,14 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) {
_defaultHazeID = hazeStage->addHaze(_defaultHaze);
}
}
}
if (!_defaultTonemapping) {
auto tonemappingStage = renderContext->_scene->getStage<TonemappingStage>();
if (tonemappingStage) {
auto tonemapping = std::make_shared<graphics::Tonemapping>();
_defaultTonemapping = tonemapping;
_defaultTonemappingID = tonemappingStage->addTonemapping(_defaultTonemapping);
}
}
}

View file

@ -32,6 +32,7 @@
#include "LightClusters.h"
#include "BackgroundStage.h"
#include "HazeStage.h"
#include "TonemappingStage.h"
#include "SurfaceGeometryPass.h"
#include "SubsurfaceScattering.h"
@ -162,11 +163,13 @@ public:
protected:
graphics::LightPointer _defaultLight;
LightStage::Index _defaultLightID{ LightStage::INVALID_INDEX };
LightStage::Index _defaultLightID { LightStage::INVALID_INDEX };
graphics::SunSkyStagePointer _defaultBackground;
BackgroundStage::Index _defaultBackgroundID{ BackgroundStage::INVALID_INDEX };
graphics::HazePointer _defaultHaze{ nullptr };
HazeStage::Index _defaultHazeID{ HazeStage::INVALID_INDEX };
BackgroundStage::Index _defaultBackgroundID { BackgroundStage::INVALID_INDEX };
graphics::HazePointer _defaultHaze { nullptr };
HazeStage::Index _defaultHazeID { HazeStage::INVALID_INDEX };
graphics::TonemappingPointer _defaultTonemapping { nullptr };
TonemappingStage::Index _defaultTonemappingID { TonemappingStage::INVALID_INDEX };
graphics::SkyboxPointer _defaultSkybox { new ProceduralSkybox() };
NetworkTexturePointer _defaultSkyboxNetworkTexture;
NetworkTexturePointer _defaultAmbientNetworkTexture;

View file

@ -13,7 +13,7 @@
#include <gpu/Context.h>
std::string HazeStage::_stageName { "HAZE_STAGE"};
std::string HazeStage::_stageName { "HAZE_STAGE" };
const HazeStage::Index HazeStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const {

View file

@ -15,7 +15,7 @@
#include "ViewFrustum.h"
std::string LightStage::_stageName { "LIGHT_STAGE"};
std::string LightStage::_stageName { "LIGHT_STAGE" };
// The bias matrix goes from homogeneous coordinates to UV coords (see http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#basic-shader)
const glm::mat4 LightStage::Shadow::_biasMatrix {
0.5, 0.0, 0.0, 0.0,

View file

@ -4,6 +4,7 @@
//
// Created by Sam Gateau 7/1/2016.
// Copyright 2016 High Fidelity, Inc.
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -17,14 +18,13 @@
#include <render/Forward.h>
#include <render/DrawTask.h>
// LightingModel is a helper class gathering in one place the flags to enable the lighting contributions
// LightingModel is a helper class gathering in one place the flags to enable the lighting contributions
class LightingModel {
public:
using UniformBufferView = gpu::BufferView;
LightingModel();
void setUnlit(bool enable);
bool isUnlitEnabled() const;
@ -76,7 +76,6 @@ public:
void setBlendshape(bool enable);
bool isBlendshapeEnabled() const;
void setAmbientOcclusion(bool enable);
bool isAmbientOcclusionEnabled() const;
void setShadow(bool enable);
@ -86,55 +85,49 @@ public:
gpu::TexturePointer getAmbientFresnelLUT() const { return _ambientFresnelLUT; }
protected:
// Class describing the uniform buffer with the transform info common to the AO shaders
// It s changing every frame
class Parameters {
public:
float enableUnlit{ 1.0f };
float enableEmissive{ 1.0f };
float enableLightmap{ 1.0f };
float enableBackground{ 1.0f };
float enableUnlit { 1.0f };
float enableEmissive { 1.0f };
float enableLightmap { 1.0f };
float enableBackground { 1.0f };
float enableScattering{ 1.0f };
float enableDiffuse{ 1.0f };
float enableSpecular{ 1.0f };
float enableAlbedo{ 1.0f };
float enableScattering { 1.0f };
float enableDiffuse { 1.0f };
float enableSpecular { 1.0f };
float enableAlbedo { 1.0f };
float enableAmbientLight{ 1.0f };
float enableDirectionalLight{ 1.0f };
float enablePointLight{ 1.0f };
float enableSpotLight{ 1.0f };
float enableAmbientLight { 1.0f };
float enableDirectionalLight { 1.0f };
float enablePointLight { 1.0f };
float enableSpotLight { 1.0f };
float showLightContour { 0.0f }; // false by default
float enableObscurance{ 1.0f };
float enableObscurance { 1.0f };
float enableMaterialTexturing { 1.0f };
float enableWireframe { 0.0f }; // false by default
float enableHaze{ 1.0f };
float enableBloom{ 1.0f };
float enableSkinning{ 1.0f };
float enableBlendshape{ 1.0f };
float enableHaze { 1.0f };
float enableBloom { 1.0f };
float enableSkinning { 1.0f };
float enableBlendshape { 1.0f };
float enableAmbientOcclusion{ 0.0f }; // false by default
float enableShadow{ 1.0f };
float spare1{ 1.0f };
float spare2{ 1.0f };
float enableAmbientOcclusion { 1.0f };
float enableShadow { 1.0f };
float spare1 { 1.0f };
float spare2 { 1.0f };
Parameters() {}
};
UniformBufferView _parametersBuffer;
static gpu::TexturePointer _ambientFresnelLUT;
};
using LightingModelPointer = std::shared_ptr<LightingModel>;
class MakeLightingModelConfig : public render::Job::Config {
Q_OBJECT
@ -168,39 +161,37 @@ class MakeLightingModelConfig : public render::Job::Config {
Q_PROPERTY(bool enableAmbientOcclusion READ isAmbientOcclusionEnabled WRITE setAmbientOcclusion NOTIFY dirty)
Q_PROPERTY(bool enableShadow READ isShadowEnabled WRITE setShadow NOTIFY dirty)
public:
MakeLightingModelConfig() : render::Job::Config() {} // Make Lighting Model is always on
bool enableUnlit{ true };
bool enableEmissive{ true };
bool enableLightmap{ true };
bool enableBackground{ true };
bool enableObscurance{ true };
bool enableUnlit { true };
bool enableEmissive { true };
bool enableLightmap { true };
bool enableBackground { true };
bool enableObscurance { true };
bool enableScattering{ true };
bool enableDiffuse{ true };
bool enableSpecular{ true };
bool enableScattering { true };
bool enableDiffuse { true };
bool enableSpecular { true };
bool enableAlbedo{ true };
bool enableAlbedo { true };
bool enableMaterialTexturing { true };
bool enableAmbientLight{ true };
bool enableDirectionalLight{ true };
bool enablePointLight{ true };
bool enableSpotLight{ true };
bool enableAmbientLight { true };
bool enableDirectionalLight { true };
bool enablePointLight { true };
bool enableSpotLight { true };
bool showLightContour { false }; // false by default
bool enableWireframe { false }; // false by default
bool enableHaze{ true };
bool enableBloom{ true };
bool enableSkinning{ true };
bool enableBlendshape{ true };
bool enableAmbientOcclusion{ false }; // false by default
bool enableShadow{ true };
bool enableHaze { true };
bool enableBloom { true };
bool enableSkinning { true };
bool enableBlendshape { true };
bool enableAmbientOcclusion { true };
bool enableShadow { true };
void setAmbientOcclusion(bool enable) { enableAmbientOcclusion = enable; emit dirty();}
bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; }

View file

@ -137,6 +137,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto backgroundFrame = currentStageFrames[1];
const auto& hazeFrame = currentStageFrames[2];
const auto& bloomFrame = currentStageFrames[3];
const auto& tonemappingFrame = currentStageFrames[4];
const auto& ambientOcclusionFrame = currentStageFrames[5];
// Shadow Task Outputs
const auto& shadowTaskOutputs = inputs.get3();
@ -198,7 +200,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto scatteringResource = task.addJob<SubsurfaceScattering>("Scattering");
// AO job
const auto ambientOcclusionInputs = AmbientOcclusionEffect::Input(lightingModel, deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying();
const auto ambientOcclusionInputs = AmbientOcclusionEffect::Input(lightingModel, deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionFrame).asVarying();
const auto ambientOcclusionOutputs = task.addJob<AmbientOcclusionEffect>("AmbientOcclusion", ambientOcclusionInputs);
const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Output>(0);
const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Output>(1);
@ -250,8 +252,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto destFramebuffer = static_cast<gpu::FramebufferPointer>(nullptr);
// Lighting Buffer ready for tone mapping
const auto toneMappingInputs = ToneMapAndResample::Input(lightingFramebuffer, destFramebuffer).asVarying();
const auto toneMappedBuffer = task.addJob<ToneMapAndResample>("ToneMapping", toneMappingInputs, depth);
const auto toneMappingInputs = ToneMapAndResample::Input(lightingFramebuffer, destFramebuffer, tonemappingFrame).asVarying();
const auto toneMappedBuffer = task.addJob<ToneMapAndResample>("ToneMapping", toneMappingInputs);
// Debugging task is happening in the "over" layer after tone mapping and just before HUD
{ // Debug the bounds of the rendered items, still look at the zbuffer

View file

@ -108,6 +108,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
const auto lightFrame = currentStageFrames[0];
const auto backgroundFrame = currentStageFrames[1];
const auto hazeFrame = currentStageFrames[2];
const auto tonemappingFrame = currentStageFrames[4];
const auto& zones = lightingStageInputs[1];
@ -178,8 +179,8 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
const auto destFramebuffer = static_cast<gpu::FramebufferPointer>(nullptr);
const auto toneMappingInputs = ToneMapAndResample::Input(resolvedFramebuffer, destFramebuffer).asVarying();
const auto toneMappedBuffer = task.addJob<ToneMapAndResample>("ToneMapping", toneMappingInputs, depth);
const auto toneMappingInputs = ToneMapAndResample::Input(resolvedFramebuffer, destFramebuffer, tonemappingFrame).asVarying();
const auto toneMappedBuffer = task.addJob<ToneMapAndResample>("ToneMapping", toneMappingInputs);
// HUD Layer
const auto renderHUDLayerInputs = RenderHUDLayerTask::Input(toneMappedBuffer, lightingModel, hudOpaque, hudTransparent, hazeFrame).asVarying();
task.addJob<RenderHUDLayerTask>("RenderHUDLayer", renderHUDLayerInputs);

View file

@ -25,10 +25,9 @@ using namespace shader::render_utils::program;
gpu::PipelinePointer ToneMapAndResample::_pipeline;
gpu::PipelinePointer ToneMapAndResample::_mirrorPipeline;
ToneMapAndResample::ToneMapAndResample(size_t depth) {
ToneMapAndResample::ToneMapAndResample() {
Parameters parameters;
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
_depth = depth;
}
void ToneMapAndResample::init() {
@ -44,13 +43,13 @@ void ToneMapAndResample::init() {
void ToneMapAndResample::setExposure(float exposure) {
auto& params = _parametersBuffer.get<Parameters>();
if (params._exposure != exposure) {
_parametersBuffer.edit<Parameters>()._exposure = exposure;
if (_exposure != exposure) {
_exposure = exposure;
_parametersBuffer.edit<Parameters>()._twoPowExposure = pow(2.0, exposure);
}
}
void ToneMapAndResample::setToneCurve(ToneCurve curve) {
void ToneMapAndResample::setCurve(TonemappingCurve curve) {
auto& params = _parametersBuffer.get<Parameters>();
if (params._toneCurve != (int)curve) {
_parametersBuffer.edit<Parameters>()._toneCurve = (int)curve;
@ -58,8 +57,9 @@ void ToneMapAndResample::setToneCurve(ToneCurve curve) {
}
void ToneMapAndResample::configure(const Config& config) {
setExposure(config.exposure);
setToneCurve((ToneCurve)config.curve);
_debug = config.debug;
_debugExposure = config.exposure;
_debugCurve = (TonemappingCurve)config.curve;
}
void ToneMapAndResample::run(const RenderContextPointer& renderContext, const Input& input, Output& output) {
@ -70,6 +70,21 @@ void ToneMapAndResample::run(const RenderContextPointer& renderContext, const In
auto lightingBuffer = input.get0()->getRenderBuffer(0);
auto destinationFramebuffer = input.get1();
const auto tonemappingFrame = input.get2();
const auto& tonemappingStage = renderContext->_scene->getStage<TonemappingStage>();
graphics::TonemappingPointer tonemapping;
if (tonemappingStage && tonemappingFrame->_tonemappings.size()) {
tonemapping = tonemappingStage->getTonemapping(tonemappingFrame->_tonemappings.front());
}
if (_debug) {
setCurve(_debugCurve);
setExposure(_debugExposure);
} else if (tonemapping) {
setCurve(tonemapping->getCurve());
setExposure(tonemapping->getExposure());
}
if (!destinationFramebuffer) {
destinationFramebuffer = args->_blitFramebuffer;

View file

@ -20,28 +20,24 @@
#include <render/Forward.h>
#include <render/DrawTask.h>
enum class ToneCurve {
// Different tone curve available
None,
Gamma22,
Reinhard,
Filmic,
};
#include "TonemappingStage.h"
class ToneMappingConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure);
Q_PROPERTY(int curve MEMBER curve WRITE setCurve);
Q_PROPERTY(bool debug MEMBER debug WRITE setDebug NOTIFY dirty);
Q_PROPERTY(int curve MEMBER curve WRITE setCurve NOTIFY dirty);
Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure NOTIFY dirty);
public:
ToneMappingConfig() : render::Job::Config(true) {}
void setDebug(bool newDebug) { debug = newDebug; emit dirty(); }
void setCurve(int newCurve) { curve = std::max(0, std::min((int)TonemappingCurve::FILMIC, newCurve)); emit dirty(); }
void setExposure(float newExposure) { exposure = newExposure; emit dirty(); }
void setCurve(int newCurve) { curve = std::max((int)ToneCurve::None, std::min((int)ToneCurve::Filmic, newCurve)); emit dirty(); }
float exposure{ 0.0f };
int curve{ (int)ToneCurve::Gamma22 };
bool debug { false };
int curve { (int)TonemappingCurve::SRGB };
float exposure { 0.0f };
signals:
void dirty();
@ -49,17 +45,14 @@ signals:
class ToneMapAndResample {
public:
ToneMapAndResample(size_t depth);
ToneMapAndResample();
virtual ~ToneMapAndResample() {}
void setCurve(TonemappingCurve curve);
void setExposure(float exposure);
float getExposure() const { return _parametersBuffer.get<Parameters>()._exposure; }
void setToneCurve(ToneCurve curve);
ToneCurve getToneCurve() const { return (ToneCurve)_parametersBuffer.get<Parameters>()._toneCurve; }
// Inputs: lightingFramebuffer, destinationFramebuffer
using Input = render::VaryingSet2<gpu::FramebufferPointer, gpu::FramebufferPointer>;
// Inputs: lightingFramebuffer, destinationFramebuffer, tonemappingFrame
using Input = render::VaryingSet3<gpu::FramebufferPointer, gpu::FramebufferPointer, TonemappingStage::FramePointer>;
using Output = gpu::FramebufferPointer;
using Config = ToneMappingConfig;
using JobModel = render::Job::ModelIO<ToneMapAndResample, Input, Output, Config>;
@ -73,22 +66,19 @@ protected:
gpu::FramebufferPointer _destinationFrameBuffer;
float _factor { 2.0f };
size_t _depth { 0 };
gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer);
private:
gpu::PipelinePointer _blitLightBuffer;
float _exposure { 0.0f };
bool _debug { false };
TonemappingCurve _debugCurve { TonemappingCurve::SRGB };
float _debugExposure { 0.0f };
// Class describing the uniform buffer with all the parameters common to the tone mapping shaders
class Parameters {
public:
float _exposure = 0.0f;
float _twoPowExposure = 1.0f;
glm::vec2 spareA;
int _toneCurve = (int)ToneCurve::Gamma22;
glm::vec3 spareB;
int _toneCurve = (int)TonemappingCurve::SRGB;
Parameters() {}
};

View file

@ -0,0 +1,56 @@
//
// TonemappingStage.cpp
//
// Created by HifiExperiments on 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TonemappingStage.h"
#include <gpu/Context.h>
std::string TonemappingStage::_stageName { "TONEMAPPING_STAGE" };
const TonemappingStage::Index TonemappingStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
TonemappingStage::Index TonemappingStage::findTonemapping(const TonemappingPointer& tonemapping) const {
auto found = _tonemappingMap.find(tonemapping);
if (found != _tonemappingMap.end()) {
return INVALID_INDEX;
} else {
return (*found).second;
}
}
TonemappingStage::Index TonemappingStage::addTonemapping(const TonemappingPointer& tonemapping) {
auto found = _tonemappingMap.find(tonemapping);
if (found == _tonemappingMap.end()) {
auto tonemappingId = _tonemappings.newElement(tonemapping);
// Avoid failing to allocate a tonemapping, just pass
if (tonemappingId != INVALID_INDEX) {
// Insert the tonemapping and its index in the reverse map
_tonemappingMap.insert(TonemappingMap::value_type(tonemapping, tonemappingId));
}
return tonemappingId;
} else {
return (*found).second;
}
}
TonemappingStage::TonemappingPointer TonemappingStage::removeTonemapping(Index index) {
TonemappingPointer removed = _tonemappings.freeElement(index);
if (removed) {
_tonemappingMap.erase(removed);
}
return removed;
}
TonemappingStageSetup::TonemappingStageSetup() {}
void TonemappingStageSetup::run(const render::RenderContextPointer& renderContext) {
auto stage = renderContext->_scene->getStage(TonemappingStage::getName());
if (!stage) {
renderContext->_scene->resetStage(TonemappingStage::getName(), std::make_shared<TonemappingStage>());
}
}

View file

@ -0,0 +1,84 @@
//
// TonemappingStage.h
//
// Created by HifiExperiments on 6/24/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_render_utils_TonemappingStage_h
#define hifi_render_utils_TonemappingStage_h
#include <graphics/Stage.h>
#include <set>
#include <unordered_map>
#include <render/IndexedContainer.h>
#include <render/Stage.h>
#include <render/Forward.h>
#include <render/DrawTask.h>
#include <graphics/Tonemapping.h>
// Tonemapping stage to set up tonemapping-related rendering tasks
class TonemappingStage : public render::Stage {
public:
static std::string _stageName;
static const std::string& getName() { return _stageName; }
using Index = render::indexed_container::Index;
static const Index INVALID_INDEX;
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
using TonemappingPointer = graphics::TonemappingPointer;
using Tonemappings = render::indexed_container::IndexedPointerVector<graphics::Tonemapping>;
using TonemappingMap = std::unordered_map<TonemappingPointer, Index>;
using TonemappingIndices = std::vector<Index>;
Index findTonemapping(const TonemappingPointer& tonemapping) const;
Index addTonemapping(const TonemappingPointer& tonemapping);
TonemappingPointer removeTonemapping(Index index);
bool checkTonemappingId(Index index) const { return _tonemappings.checkIndex(index); }
Index getNumTonemappings() const { return _tonemappings.getNumElements(); }
Index getNumFreeTonemappings() const { return _tonemappings.getNumFreeIndices(); }
Index getNumAllocatedTonemappings() const { return _tonemappings.getNumAllocatedIndices(); }
TonemappingPointer getTonemapping(Index tonemappingId) const {
return _tonemappings.get(tonemappingId);
}
Tonemappings _tonemappings;
TonemappingMap _tonemappingMap;
class Frame {
public:
Frame() {}
void clear() { _tonemappings.clear(); }
void pushTonemapping(TonemappingStage::Index index) { _tonemappings.emplace_back(index); }
TonemappingStage::TonemappingIndices _tonemappings;
};
using FramePointer = std::shared_ptr<Frame>;
Frame _currentFrame;
};
using TonemappingStagePointer = std::shared_ptr<TonemappingStage>;
class TonemappingStageSetup {
public:
using JobModel = render::Job::Model<TonemappingStageSetup>;
TonemappingStageSetup();
void run(const render::RenderContextPointer& renderContext);
protected:
};
#endif

View file

@ -15,6 +15,8 @@
#include "BackgroundStage.h"
#include "HazeStage.h"
#include "BloomStage.h"
#include "TonemappingStage.h"
#include "AmbientOcclusionStage.h"
#include <render/TransitionStage.h>
#include <render/HighlightStage.h>
#include "DeferredLightingEffect.h"
@ -24,6 +26,8 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render
task.addJob<BackgroundStageSetup>("BackgroundStageSetup");
task.addJob<HazeStageSetup>("HazeStageSetup");
task.addJob<BloomStageSetup>("BloomStageSetup");
task.addJob<TonemappingStageSetup>("TonemappingStageSetup");
task.addJob<AmbientOcclusionStageSetup>("AmbientOcclusionStageSetup");
task.addJob<render::TransitionStageSetup>("TransitionStageSetup");
task.addJob<render::HighlightStageSetup>("HighlightStageSetup");

View file

@ -26,6 +26,7 @@
#include "DeferredLightingEffect.h"
#include "BloomStage.h"
#include "TonemappingStage.h"
namespace ru {
using render_utils::slot::texture::Texture;
@ -71,6 +72,14 @@ void SetupZones::run(const RenderContextPointer& context, const Input& input) {
assert(bloomStage);
bloomStage->_currentFrame.clear();
auto tonemappingStage = context->_scene->getStage<TonemappingStage>();
assert(tonemappingStage);
tonemappingStage->_currentFrame.clear();
auto ambientOcclusionStage = context->_scene->getStage<AmbientOcclusionStage>();
assert(ambientOcclusionStage);
ambientOcclusionStage->_currentFrame.clear();
// call render over the zones to grab their components in the correct order first...
render::renderItems(context, input);
@ -80,6 +89,8 @@ void SetupZones::run(const RenderContextPointer& context, const Input& input) {
backgroundStage->_currentFrame.pushBackground(0);
hazeStage->_currentFrame.pushHaze(0);
bloomStage->_currentFrame.pushBloom(INVALID_INDEX);
tonemappingStage->_currentFrame.pushTonemapping(0);
ambientOcclusionStage->_currentFrame.pushAmbientOcclusion(INVALID_INDEX);
}
const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
@ -105,6 +116,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getAmbientPipeline() {
}
return _ambientPipeline;
}
const gpu::PipelinePointer& DebugZoneLighting::getBackgroundPipeline() {
if (!_backgroundPipeline) {
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::zone_drawSkybox);

View file

@ -16,8 +16,8 @@
<@include render-utils/ShaderConstants.h@>
struct ToneMappingParams {
vec4 _exp_2powExp_s0_s1;
ivec4 _toneCurve_s0_s1_s2;
float _2powExp;
int _toneCurve;
};
const float GAMMA_22 = 2.2;
@ -31,17 +31,17 @@ LAYOUT(binding=RENDER_UTILS_BUFFER_TM_PARAMS) uniform toneMappingParamsBuffer {
ToneMappingParams params;
};
float getTwoPowExposure() {
return params._exp_2powExp_s0_s1.y;
return params._2powExp;
}
int getToneCurve() {
return params._toneCurve_s0_s1_s2.x;
return params._toneCurve;
}
LAYOUT(binding=RENDER_UTILS_TEXTURE_TM_COLOR) uniform sampler2D colorMap;
layout(location=0) in vec2 varTexCoord0;
layout(location=0) out vec4 outFragColor;
void main(void) {
<@if HIFI_USE_MIRRORED@>
vec4 fragColorRaw = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));

View file

@ -0,0 +1,24 @@
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AmbientOcclusionTechnique.h"
const char* ambientOcclusionTechniqueNames[] = {
"ssao",
"hbao"
};
static const size_t AO_TECHNIQUE_NAMES = (sizeof(ambientOcclusionTechniqueNames) / sizeof(ambientOcclusionTechniqueNames[0]));
QString AmbientOcclusionTechniqueHelpers::getNameForAmbientOcclusionTechnique(AmbientOcclusionTechnique technique) {
if (((int)technique <= 0) || ((int)technique >= (int)AO_TECHNIQUE_NAMES)) {
technique = (AmbientOcclusionTechnique)0;
}
return ambientOcclusionTechniqueNames[(int)technique];
}

View file

@ -0,0 +1,38 @@
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AmbientOcclusionTechnique_h
#define hifi_AmbientOcclusionTechnique_h
#include "QString"
/*@jsdoc
* <p>The technique used for calculating ambient occlusion. Different techniques have different tradeoffs.</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"ssao"</code></td><td>A basic screen-space AO effect.</td></tr>
* <tr><td><code>"hbao"</code></td><td>A form of SSAO that uses the depth buffer for better AO detail, sometimes at the expense of performance.</td></tr>
* </tbody>
* </table>
* @typedef {string} AmbientOcclusionTechnique
*/
enum class AmbientOcclusionTechnique {
SSAO = 0,
HBAO,
};
class AmbientOcclusionTechniqueHelpers {
public:
static QString getNameForAmbientOcclusionTechnique(AmbientOcclusionTechnique curve);
};
#endif // hifi_AmbientOcclusionTechnique_h

View file

@ -0,0 +1,26 @@
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TonemappingCurve.h"
const char* tonemappingCurveNames[] = {
"rgb",
"srgb",
"reinhard",
"filmic"
};
static const size_t TONEMAPPING_CURVE_NAMES = (sizeof(tonemappingCurveNames) / sizeof(tonemappingCurveNames[0]));
QString TonemappingCurveHelpers::getNameForTonemappingCurve(TonemappingCurve curve) {
if (((int)curve <= 0) || ((int)curve >= (int)TONEMAPPING_CURVE_NAMES)) {
curve = (TonemappingCurve)0;
}
return tonemappingCurveNames[(int)curve];
}

View file

@ -0,0 +1,42 @@
//
// Created by HifiExperiments on 6/23/24
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_TonemappingCurve_h
#define hifi_TonemappingCurve_h
#include "QString"
/*@jsdoc
* <p>The tonemapping curve applied to the final rendering.</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>"rgb"</code></td><td>No tonemapping, colors are kept in RGB.</td></tr>
* <tr><td><code>"srgb"</code></td><td>Colors are converted to sRGB.</td></tr>
* <tr><td><code>"reinhard"</code></td><td>Reinhard tonemapping is applied.</td></tr>
* <tr><td><code>"filmic"</code></td><td>Filmic tonemapping is applied.</td></tr>
* </tbody>
* </table>
* @typedef {string} TonemappingCurve
*/
enum class TonemappingCurve {
RGB = 0,
SRGB,
REINHARD,
FILMIC
};
class TonemappingCurveHelpers {
public:
static QString getNameForTonemappingCurve(TonemappingCurve curve);
};
#endif // hifi_TonemappingCurve_h

View file

@ -55,6 +55,7 @@ Rectangle {
Column {
Repeater {
model: [
"debugEnabled:debug",
"horizonBased:horizonBased",
"jitterEnabled:jitterEnabled",
"ditheringEnabled:ditheringEnabled",
@ -72,7 +73,7 @@ Rectangle {
Column {
Repeater {
model: [
"debugEnabled:showCursorPixel"
"showCursorPixel:showCursorPixel"
]
HifiControls.CheckBox {
boxSize: 20
@ -100,8 +101,6 @@ Rectangle {
]
}
TabView {
anchors.left: parent.left
anchors.right: parent.right

View file

@ -14,15 +14,11 @@ import "../../lib/prop" as Prop
Column {
anchors.left: parent.left
anchors.right: parent.right
Prop.PropScalar {
label: "Exposure"
anchors.right: parent.right
Prop.PropBool {
label: "Debug"
object: Render.getConfig("RenderMainView.ToneMapping")
property: "exposure"
min: -4
max: 4
anchors.left: parent.left
anchors.right: parent.right
property: "debug"
}
Prop.PropEnum {
label: "Tone Curve"
@ -35,6 +31,15 @@ Column {
"Filmic",
]
anchors.left: parent.left
anchors.right: parent.right
}
anchors.right: parent.right
}
Prop.PropScalar {
label: "Exposure"
object: Render.getConfig("RenderMainView.ToneMapping")
property: "exposure"
min: -4
max: 4
anchors.left: parent.left
anchors.right: parent.right
}
}

View file

@ -165,6 +165,48 @@
"bloom.bloomSize": {
"tooltip": "The radius of bloom. The higher the value, the larger the bloom."
},
"tonemappingMode": {
"tooltip": "Configures the tonemapping applied to the final render."
},
"tonemapping.curve": {
"tooltip": "The tonemapping curve used."
},
"tonemapping.exposure": {
"tooltip": "The exposure used during tonemapping."
},
"ambientOcclusionMode": {
"tooltip": "Configures the ambient occlusion in this zone."
},
"ambientOcclusion.technique": {
"tooltip": "The ambient occlusion technique used. Different techniques have different tradeoffs."
},
"ambientOcclusion.jitter": {
"tooltip": "Whether or not the ambient occlusion sampling is jittered."
},
"ambientOcclusion.resolutionLevel": {
"tooltip": "How high the resolution of the ambient occlusion buffer should be. Higher levels mean lower resolution buffers."
},
"ambientOcclusion.edgeSharpness": {
"tooltip": "How much to sharpen the edges during the ambient occlusion blurring."
},
"ambientOcclusion.blurRadius": {
"tooltip": "The radius used for blurring, in pixels."
},
"ambientOcclusion.aoRadius": {
"tooltip": "The radius used for ambient occlusion."
},
"ambientOcclusion.aoObscuranceLevel": {
"tooltip": "Intensify or dim ambient occlusion."
},
"ambientOcclusion.aoFalloffAngle": {
"tooltip": "The falloff angle for the AO calculation."
},
"ambientOcclusion.aoSamplingAmount": {
"tooltip": "The fraction of AO samples to use, out of the maximum for each technique."
},
"ambientOcclusion.ssaoNumSpiralTurns": {
"tooltip": "The angle span used to distribute the AO samples ray directions. SSAO only."
},
"audio.reverbEnabled": {
"tooltip": "If reverb should be enabled for listeners in this zone."
},

View file

@ -618,6 +618,124 @@ const GROUPS = [
}
]
},
{
id: "zone_tonemapping",
label: "ZONE TONEMAPPING",
properties: [
{
label: "Tonemapping",
type: "dropdown",
options: { inherit: "Inherit", disabled: "Off", enabled: "On" },
propertyID: "tonemappingMode",
},
{
label: "Curve",
type: "dropdown",
options: { rgb: "RGB", srgb: "sRGB", reinhard: "Reinhard", filmic: "Filmic" },
propertyID: "tonemapping.curve",
showPropertyRule: { "tonemappingMode": "enabled" },
},
{
label: "Exposure",
type: "number-draggable",
min: -4.0,
max: 4.0,
step: 0.1,
decimals: 1,
propertyID: "tonemapping.exposure",
showPropertyRule: { "tonemappingMode": "enabled" },
}
]
},
{
id: "zone_ambient_occlusion",
label: "ZONE AMBIENT OCCLUSION",
properties: [
{
label: "Ambient Occlusion",
type: "dropdown",
options: { inherit: "Inherit", disabled: "Off", enabled: "On" },
propertyID: "ambientOcclusionMode",
},
//{
// label: "Technique",
// type: "dropdown",
// options: { ssao: "SSAO", hbao: "HBAO" },
// propertyID: "ambientOcclusion.technique",
// showPropertyRule: { "ambientOcclusionMode": "enabled" },
//},
{
label: "Jitter",
type: "bool",
propertyID: "ambientOcclusion.jitter",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Resolution Level",
type: "number-draggable",
step: 1,
decimals: 0,
propertyID: "ambientOcclusion.resolutionLevel",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Edge Sharpness",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.edgeSharpness",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Blur Radius (pixels)",
type: "number-draggable",
step: 1,
decimals: 0,
propertyID: "ambientOcclusion.blurRadius",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "AO Radius",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.aoRadius",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Intensity",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.aoObscuranceLevel",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Falloff Angle",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.aoFalloffAngle",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Sampling Amount",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.aoSamplingAmount",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
},
{
label: "Num Spiral Turns",
type: "number-draggable",
step: 0.01,
decimals: 2,
propertyID: "ambientOcclusion.ssaoNumSpiralTurns",
showPropertyRule: { "ambientOcclusionMode": "enabled" },
}
]
},
{
id: "zone_avatar_priority",
label: "ZONE AVATAR PRIORITY",
@ -1938,8 +2056,9 @@ const GROUPS_PER_TYPE = {
None: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
Shape: [ 'base', 'shape', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
Text: [ 'base', 'text', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze',
'zone_bloom', 'zone_avatar_priority', 'zone_audio', 'spatial', 'behavior', 'scripts', 'physics' ],
Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze',
'zone_bloom', 'zone_tonemapping', 'zone_ambient_occlusion', 'zone_avatar_priority',
'zone_audio', 'spatial', 'behavior', 'scripts', 'physics' ],
Model: [ 'base', 'model', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],
Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ],

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B