From 0dd8d2d3d4d3ca5555b5beb03392e19f89580e13 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Aug 2018 18:18:58 -0700 Subject: [PATCH 1/3] working on enabling bloom --- .../src/RenderableZoneEntityItem.cpp | 49 ++++++ .../src/RenderableZoneEntityItem.h | 31 ++-- libraries/entities/src/BloomPropertyGroup.cpp | 159 +++++++++++++++++ libraries/entities/src/BloomPropertyGroup.h | 94 ++++++++++ .../entities/src/EntityItemProperties.cpp | 51 +++++- libraries/entities/src/EntityItemProperties.h | 4 + libraries/entities/src/EntityPropertyFlags.h | 5 + libraries/entities/src/ZoneEntityItem.cpp | 165 ++++++++++-------- libraries/entities/src/ZoneEntityItem.h | 14 +- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../render-utils/src/UpdateSceneTask.cpp | 2 + 12 files changed, 483 insertions(+), 96 deletions(-) create mode 100644 libraries/entities/src/BloomPropertyGroup.cpp create mode 100644 libraries/entities/src/BloomPropertyGroup.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index c5035431f6..f23e8096f1 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -64,6 +64,13 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity _hazeIndex = INVALID_INDEX; } } + + if (_bloomStage) { + if (!BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomStage->removeBloom(_bloomIndex); + _bloomIndex = INVALID_INDEX; + } + } } void ZoneEntityRenderer::doRender(RenderArgs* args) { @@ -112,6 +119,11 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { assert(_hazeStage); } + if (!_bloomStage) { + _bloomStage = args->_scene->getStage(); + assert(_bloomStage); + } + { // Sun // Need an update ? if (_needSunUpdate) { @@ -161,6 +173,15 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { } } + { + if (_needBloomUpdate) { + if (BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomIndex = _bloomStage->addBloom(_bloom); + } + _needBloomUpdate = false; + } + } + if (_visible) { // Finally, push the lights visible in the frame // @@ -190,6 +211,11 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { if (_hazeMode != COMPONENT_MODE_INHERIT) { _hazeStage->_currentFrame.pushHaze(_hazeIndex); } + + // Bloom only if the mode is not inherit, as the model deals with on/off + if (_bloomMode != COMPONENT_MODE_INHERIT) { + _bloomStage->_currentFrame.pushBloom(_bloomIndex); + } } } @@ -211,6 +237,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen bool ambientLightChanged = entity->ambientLightPropertiesChanged(); bool skyboxChanged = entity->skyboxPropertiesChanged(); bool hazeChanged = entity->hazePropertiesChanged(); + bool bloomChanged = entity->bloomPropertiesChanged(); entity->resetRenderingPropertiesChanged(); _lastPosition = entity->getWorldPosition(); @@ -221,6 +248,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen _ambientLightProperties = entity->getAmbientLightProperties(); _skyboxProperties = entity->getSkyboxProperties(); _hazeProperties = entity->getHazeProperties(); + _bloomProperties = entity->getBloomProperties(); #if 0 if (_lastShapeURL != _typedEntity->getCompoundShapeURL()) { @@ -258,6 +286,10 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen if (hazeChanged) { updateHazeFromEntity(entity); } + + if (bloomChanged) { + updateBloomFromEntity(entity); + } } void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { @@ -276,6 +308,7 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (entity->keyLightPropertiesChanged() || entity->ambientLightPropertiesChanged() || entity->hazePropertiesChanged() || + entity->bloomPropertiesChanged() || entity->skyboxPropertiesChanged()) { return true; @@ -388,6 +421,18 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) haze->setTransform(entity->getTransform().getMatrix()); } +void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity) { + setBloomMode((ComponentMode)entity->getBloomMode()); + + const auto& bloom = editBloom(); + + const uint32_t bloomMode = entity->getBloomMode(); + bloom->setBloomActive(bloomMode == COMPONENT_MODE_ENABLED); + bloom->setBloomIntensity(_bloomProperties.getBloomIntensity()); + bloom->setBloomThreshold(_bloomProperties.getBloomThreshold()); + bloom->setBloomSize(_bloomProperties.getBloomSize()); +} + void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer& entity) { setSkyboxMode((ComponentMode)entity->getSkyboxMode()); @@ -510,6 +555,10 @@ void ZoneEntityRenderer::setSkyboxMode(ComponentMode mode) { _skyboxMode = mode; } +void ZoneEntityRenderer::setBloomMode(ComponentMode mode) { + _bloomMode = mode; +} + void ZoneEntityRenderer::setSkyboxColor(const glm::vec3& color) { editSkybox()->setColor(color); } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index c48679e5d4..3e2690e1bd 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -1,7 +1,6 @@ // // RenderableZoneEntityItem.h // -// // Created by Clement on 4/22/15. // Copyright 2015 High Fidelity, Inc. // @@ -15,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "RenderableEntityItem.h" #include @@ -50,6 +51,7 @@ private: void updateAmbientLightFromEntity(const TypedEntityPointer& entity); void updateHazeFromEntity(const TypedEntityPointer& entity); void updateKeyBackgroundFromEntity(const TypedEntityPointer& entity); + void updateBloomFromEntity(const TypedEntityPointer& entity); void updateAmbientMap(); void updateSkyboxMap(); void setAmbientURL(const QString& ambientUrl); @@ -59,6 +61,7 @@ private: void setKeyLightMode(ComponentMode mode); void setAmbientLightMode(ComponentMode mode); void setSkyboxMode(ComponentMode mode); + void setBloomMode(ComponentMode mode); void setSkyboxColor(const glm::vec3& color); void setProceduralUserData(const QString& userData); @@ -68,6 +71,7 @@ private: graphics::SunSkyStagePointer editBackground() { _needBackgroundUpdate = true; return _background; } graphics::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); } graphics::HazePointer editHaze() { _needHazeUpdate = true; return _haze; } + graphics::BloomPointer editBloom() { _needBloomUpdate = true; return _bloom; } glm::vec3 _lastPosition; glm::vec3 _lastDimensions; @@ -82,36 +86,43 @@ private: #endif LightStagePointer _stage; - const graphics::LightPointer _sunLight{ std::make_shared() }; - const graphics::LightPointer _ambientLight{ std::make_shared() }; - const graphics::SunSkyStagePointer _background{ std::make_shared() }; - const graphics::HazePointer _haze{ std::make_shared() }; + const graphics::LightPointer _sunLight { std::make_shared() }; + const graphics::LightPointer _ambientLight { std::make_shared() }; + const graphics::SunSkyStagePointer _background { std::make_shared() }; + const graphics::HazePointer _haze { std::make_shared() }; + const graphics::BloomPointer _bloom { std::make_shared() }; 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 }; - indexed_container::Index _sunIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _shadowIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _ambientIndex{ LightStage::INVALID_INDEX }; + indexed_container::Index _sunIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _shadowIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _ambientIndex { LightStage::INVALID_INDEX }; BackgroundStagePointer _backgroundStage; - BackgroundStage::Index _backgroundIndex{ BackgroundStage::INVALID_INDEX }; + BackgroundStage::Index _backgroundIndex { BackgroundStage::INVALID_INDEX }; HazeStagePointer _hazeStage; - HazeStage::Index _hazeIndex{ HazeStage::INVALID_INDEX }; + HazeStage::Index _hazeIndex { HazeStage::INVALID_INDEX }; + + BloomStagePointer _bloomStage; + BloomStage::Index _bloomIndex { BloomStage::INVALID_INDEX }; bool _needUpdate{ true }; bool _needSunUpdate{ true }; bool _needAmbientUpdate{ true }; bool _needBackgroundUpdate{ true }; bool _needHazeUpdate{ true }; + bool _needBloomUpdate { true }; KeyLightPropertyGroup _keyLightProperties; AmbientLightPropertyGroup _ambientLightProperties; HazePropertyGroup _hazeProperties; SkyboxPropertyGroup _skyboxProperties; + BloomPropertyGroup _bloomProperties; // More attributes used for rendering: QString _ambientTextureURL; diff --git a/libraries/entities/src/BloomPropertyGroup.cpp b/libraries/entities/src/BloomPropertyGroup.cpp new file mode 100644 index 0000000000..2c4d46ab35 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.cpp @@ -0,0 +1,159 @@ +// +// BloomPropertyGroup.cpp +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "BloomPropertyGroup.h" + +#include + +#include "EntityItemProperties.h" +#include "EntityItemPropertiesMacros.h" + +void BloomPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); +} + +void BloomPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomIntensity, float, setBloomIntensity); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomThreshold, float, setBloomThreshold); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomSize, float, setBloomSize); +} + +void BloomPropertyGroup::merge(const BloomPropertyGroup& other) { + COPY_PROPERTY_IF_CHANGED(bloomIntensity); + COPY_PROPERTY_IF_CHANGED(bloomThreshold); + COPY_PROPERTY_IF_CHANGED(bloomSize); +} + +void BloomPropertyGroup::debugDump() const { + qCDebug(entities) << " BloomPropertyGroup: ---------------------------------------------"; + qCDebug(entities) << " _bloomIntensity:" << _bloomIntensity; + qCDebug(entities) << " _bloomThreshold:" << _bloomThreshold; + qCDebug(entities) << " _bloomSize:" << _bloomSize; +} + +void BloomPropertyGroup::listChangedProperties(QList& out) { + if (bloomIntensityChanged()) { + out << "bloom-bloomIntensity"; + } + if (bloomThresholdChanged()) { + out << "bloom-bloomThreshold"; + } + if (bloomSizeChanged()) { + out << "bloom-bloomSize"; + } +} + +bool BloomPropertyGroup::appendToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); + + return true; +} + +bool BloomPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) { + int bytesRead = 0; + bool overwriteLocalData = true; + bool somethingChanged = false; + + READ_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_INTENSITY, BloomIntensity); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_THRESHOLD, BloomThreshold); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_SIZE, BloomSize); + + processedBytes += bytesRead; + + Q_UNUSED(somethingChanged); + + return true; +} + +void BloomPropertyGroup::markAllChanged() { + _bloomIntensityChanged = true; + _bloomThresholdChanged = true; + _bloomSizeChanged = true; +} + +EntityPropertyFlags BloomPropertyGroup::getChangedProperties() const { + EntityPropertyFlags changedProperties; + + CHECK_PROPERTY_CHANGE(PROP_BLOOM_INTENSITY, bloomIntensity); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_THRESHOLD, bloomThreshold); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_SIZE, bloomSize); + + return changedProperties; +} + +void BloomPropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomIntensity, getBloomIntensity); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomThreshold, getBloomThreshold); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomSize, getBloomSize); +} + +bool BloomPropertyGroup::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomIntensity, bloomIntensity, setBloomIntensity); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomThreshold, bloomThreshold, setBloomThreshold); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomSize, bloomSize, setBloomSize); + + return somethingChanged; +} + +EntityPropertyFlags BloomPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties; + + requestedProperties += PROP_BLOOM_INTENSITY; + requestedProperties += PROP_BLOOM_THRESHOLD; + requestedProperties += PROP_BLOOM_SIZE; + + return requestedProperties; +} + +void BloomPropertyGroup::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_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); +} + +int BloomPropertyGroup::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_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + return bytesRead; +} diff --git a/libraries/entities/src/BloomPropertyGroup.h b/libraries/entities/src/BloomPropertyGroup.h new file mode 100644 index 0000000000..a1f9b6d748 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.h @@ -0,0 +1,94 @@ +// +// BloomPropertyGroup.h +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_BloomPropertyGroup_h +#define hifi_BloomPropertyGroup_h + +#include +#include + +#include + +#include "PropertyGroup.h" +#include "EntityItemPropertiesMacros.h" + +class EntityItemProperties; +class EncodeBitstreamParams; +class OctreePacketData; +class EntityTreeElementExtraEncodeData; +class ReadBitstreamToTreeParams; + +static const float INITIAL_BLOOM_INTENSITY { 0.25f }; +static const float INITIAL_BLOOM_THRESHOLD { 0.7f }; +static const float INITIAL_BLOOM_SIZE { 0.9f }; + +/**jsdoc + * Bloom is defined by the following properties. + * @typedef {object} Entities.Bloom + * + * @property {number} bloomIntensity=0.25 - The intensity of the bloom effect. + * @property {number} bloomThreshold=0.7 - The threshold for the bloom effect. + * @property {number} bloomSize=0.9 - The size of the bloom effect. + */ +class BloomPropertyGroup : public PropertyGroup { +public: + // EntityItemProperty related helpers + virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, + QScriptEngine* engine, bool skipDefaults, + EntityItemProperties& defaultEntityProperties) const override; + virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) override; + + void merge(const BloomPropertyGroup& other); + + virtual void debugDump() const override; + virtual void listChangedProperties(QList& 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(PROP_BLOOM_INTENSITY, BloomIntensity, bloomIntensity, float, INITIAL_BLOOM_INTENSITY); + DEFINE_PROPERTY(PROP_BLOOM_THRESHOLD, BloomThreshold, bloomThreshold, float, INITIAL_BLOOM_THRESHOLD); + DEFINE_PROPERTY(PROP_BLOOM_SIZE, BloomSize, bloomSize, float, INITIAL_BLOOM_SIZE); + +}; + +#endif // hifi_BloomPropertyGroup_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1f9bf2eb18..68d0e6aed4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -37,6 +37,7 @@ AnimationPropertyGroup EntityItemProperties::_staticAnimation; SkyboxPropertyGroup EntityItemProperties::_staticSkybox; HazePropertyGroup EntityItemProperties::_staticHaze; +BloomPropertyGroup EntityItemProperties::_staticBloom; KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; AmbientLightPropertyGroup EntityItemProperties::_staticAmbientLight; @@ -84,6 +85,7 @@ void EntityItemProperties::debugDump() const { getHaze().debugDump(); getKeyLight().debugDump(); getAmbientLight().debugDump(); + getBloom().debugDump(); qCDebug(entities) << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); @@ -211,6 +213,10 @@ QString EntityItemProperties::getHazeModeAsString() const { return getComponentModeAsString(_hazeMode); } +QString EntityItemProperties::getBloomModeAsString() const { + return getComponentModeAsString(_bloomMode); +} + QString EntityItemProperties::getComponentModeString(uint32_t mode) { // return "inherit" if mode is not valid if (mode < COMPONENT_MODE_ITEM_COUNT) { @@ -235,6 +241,15 @@ void EntityItemProperties::setHazeModeFromString(const QString& hazeMode) { } } +void EntityItemProperties::setBloomModeFromString(const QString& bloomMode) { + auto result = findComponent(bloomMode); + + if (result != COMPONENT_MODES.end()) { + _bloomMode = result->first; + _bloomModeChanged = true; + } +} + QString EntityItemProperties::getKeyLightModeAsString() const { return getComponentModeAsString(_keyLightMode); } @@ -394,6 +409,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEY_LIGHT_MODE, keyLightMode); CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_MODE, bloomMode); CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); @@ -454,6 +470,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { changedProperties += _ambientLight.getChangedProperties(); changedProperties += _skybox.getChangedProperties(); changedProperties += _haze.getChangedProperties(); + changedProperties += _bloom.getChangedProperties(); return changedProperties; } @@ -1164,6 +1181,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * "enabled": The haze properties of this zone are enabled, overriding the haze from any enclosing zone. * @property {Entities.Haze} haze - The haze properties of the zone. * + * @property {string} bloomMode="inherit" - Configures the bloom in the zone. Possible values:
+ * "inherit": The bloom from any enclosing zone continues into this zone.
+ * "disabled": The bloom from any enclosing zone and the bloom of this zone are disabled in this zone.
+ * "enabled": The bloom properties of this zone are enabled, overriding the bloom from any enclosing zone. + * @property {Entities.Bloom} bloom - The bloom properties of the zone. + * * @property {boolean} flyingAllowed=true - If true then visitors can fly in the zone; otherwise they cannot. * @property {boolean} ghostingAllowed=true - If true then visitors with avatar collisions turned off will not * collide with content in the zone; otherwise visitors will always collide with content in the zone. @@ -1382,6 +1405,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString()); _haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString()); + _bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); @@ -1630,6 +1656,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(keyLightMode, KeyLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(bloomMode, BloomMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, vec3, setVoxelVolumeSize); @@ -1662,6 +1689,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool _ambientLight.copyFromScriptValue(object, _defaultSettings); _skybox.copyFromScriptValue(object, _defaultSettings); _haze.copyFromScriptValue(object, _defaultSettings); + _bloom.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(xTextureURL, QString, setXTextureURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL); @@ -1803,6 +1831,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(keyLightMode); COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); + COPY_PROPERTY_IF_CHANGED(bloomMode); COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); @@ -1825,6 +1854,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { _ambientLight.merge(other._ambientLight); _skybox.merge(other._skybox); _haze.merge(other._haze); + _bloom.merge(other._bloom); COPY_PROPERTY_IF_CHANGED(xTextureURL); COPY_PROPERTY_IF_CHANGED(yTextureURL); @@ -2096,6 +2126,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_RANGE, Haze, haze, HazeKeyLightRange, hazeKeyLightRange); ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_ALTITUDE, Haze, haze, HazeKeyLightAltitude, hazeKeyLightAltitude); + ADD_PROPERTY_TO_MAP(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); + ADD_PROPERTY_TO_MAP(PROP_KEY_LIGHT_MODE, KeyLightMode, keyLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t); @@ -2357,6 +2392,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticHaze.setProperties(properties); _staticHaze.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode()); + _staticBloom.setProperties(properties); + _staticBloom.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)properties.getKeyLightMode()); APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)properties.getAmbientLightMode()); APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)properties.getSkyboxMode()); @@ -2731,6 +2770,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HAZE_MODE, uint32_t, setHazeMode); properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode); + properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); @@ -3044,10 +3086,12 @@ void EntityItemProperties::markAllChanged() { _skyboxModeChanged = true; _ambientLightModeChanged = true; _hazeModeChanged = true; + _bloomModeChanged = true; _animation.markAllChanged(); _skybox.markAllChanged(); _haze.markAllChanged(); + _bloom.markAllChanged(); _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; @@ -3442,15 +3486,15 @@ QList EntityItemProperties::listChangedProperties() { if (hazeModeChanged()) { out += "hazeMode"; } - + if (bloomModeChanged()) { + out += "bloomMode"; + } if (keyLightModeChanged()) { out += "keyLightMode"; } - if (ambientLightModeChanged()) { out += "ambientLightMode"; } - if (skyboxModeChanged()) { out += "skyboxMode"; } @@ -3581,6 +3625,7 @@ QList EntityItemProperties::listChangedProperties() { getAmbientLight().listChangedProperties(out); getSkybox().listChangedProperties(out); getHaze().listChangedProperties(out); + getBloom().listChangedProperties(out); return out; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 04e54c54a5..50305345de 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -42,6 +42,7 @@ #include "SimulationOwner.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include "TextEntityItem.h" #include "ZoneEntityItem.h" @@ -195,9 +196,11 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); + DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup); DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); + DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); @@ -533,6 +536,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, KeyLightMode, keyLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientLightMode, ambientLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, SkyboxMode, skyboxMode, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, BloomMode, bloomMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cloneable, cloneable, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, CloneLifetime, cloneLifetime, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 156c5d9dd4..3932730661 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -257,6 +257,11 @@ enum EntityPropertyList { PROP_SPIN_SPREAD, PROP_PARTICLE_ROTATE_WITH_ENTITY, + PROP_BLOOM_MODE, + PROP_BLOOM_INTENSITY, + PROP_BLOOM_THRESHOLD, + PROP_BLOOM_SIZE, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index f2550e5d3c..a7dfa1a41e 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -47,33 +47,27 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - // Contains a QString property, must be synchronized + // Contain QString properties, must be synchronized withReadLock([&] { _keyLightProperties.getProperties(properties); - }); - - withReadLock([&] { _ambientLightProperties.getProperties(properties); + _skyboxProperties.getProperties(properties); }); + _hazeProperties.getProperties(properties); + _bloomProperties.getProperties(properties); COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); - // Contains a QString property, must be synchronized - withReadLock([&] { - _skyboxProperties.getProperties(properties); - }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(filterURL, getFilterURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(hazeMode, getHazeMode); - _hazeProperties.getProperties(properties); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightMode, getKeyLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientLightMode, getAmbientLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(skyboxMode, getSkyboxMode); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(bloomMode, getBloomMode); return properties; } @@ -102,32 +96,27 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie // Contains a QString property, must be synchronized withWriteLock([&] { _keyLightPropertiesChanged = _keyLightProperties.setProperties(properties); - }); - withWriteLock([&] { _ambientLightPropertiesChanged = _ambientLightProperties.setProperties(properties); + _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); }); + _hazePropertiesChanged = _hazeProperties.setProperties(properties); + _bloomPropertiesChanged = _bloomProperties.setProperties(properties); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); - // Contains a QString property, must be synchronized - withWriteLock([&] { - _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); - }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(filterURL, setFilterURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(hazeMode, setHazeMode); - _hazePropertiesChanged = _hazeProperties.setProperties(properties); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightMode, setKeyLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientLightMode, setAmbientLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(skyboxMode, setSkyboxMode); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(bloomMode, setBloomMode); somethingChanged = somethingChanged || _keyLightPropertiesChanged || _ambientLightPropertiesChanged || - _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged; + _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged || _bloomPropertiesChanged; return somethingChanged; } @@ -139,54 +128,67 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - int bytesFromKeylight; - withWriteLock([&] { - bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); - }); + { + int bytesFromKeylight; + withWriteLock([&] { + bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _keyLightPropertiesChanged; + bytesRead += bytesFromKeylight; + dataAt += bytesFromKeylight; + } - somethingChanged = somethingChanged || _keyLightPropertiesChanged; - bytesRead += bytesFromKeylight; - dataAt += bytesFromKeylight; + { + int bytesFromAmbientlight; + withWriteLock([&] { + bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _ambientLightPropertiesChanged; + bytesRead += bytesFromAmbientlight; + dataAt += bytesFromAmbientlight; + } - int bytesFromAmbientlight; - withWriteLock([&] { - bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); - }); + { + int bytesFromSkybox; + withWriteLock([&] { + bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); + }); + somethingChanged = somethingChanged || _skyboxPropertiesChanged; + bytesRead += bytesFromSkybox; + dataAt += bytesFromSkybox; + } - somethingChanged = somethingChanged || _ambientLightPropertiesChanged; - bytesRead += bytesFromAmbientlight; - dataAt += bytesFromAmbientlight; + { + int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _hazePropertiesChanged); + somethingChanged = somethingChanged || _hazePropertiesChanged; + bytesRead += bytesFromHaze; + dataAt += bytesFromHaze; + } + + { + int bytesFromBloom = _bloomProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _bloomPropertiesChanged); + somethingChanged = somethingChanged || _bloomPropertiesChanged; + bytesRead += bytesFromBloom; + dataAt += bytesFromBloom; + } READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); - int bytesFromSkybox; - withWriteLock([&] { - bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); - }); - somethingChanged = somethingChanged || _skyboxPropertiesChanged; - bytesRead += bytesFromSkybox; - dataAt += bytesFromSkybox; - READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed); READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed); READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL); READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint32_t, setHazeMode); - - int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _hazePropertiesChanged); - - somethingChanged = somethingChanged || _hazePropertiesChanged; - bytesRead += bytesFromHaze; - dataAt += bytesFromHaze; - READ_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); + READ_ENTITY_PROPERTY(PROP_BLOOM_MODE, uint32_t, setBloomMode); return bytesRead; } @@ -196,29 +198,24 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p withReadLock([&] { requestedProperties += _keyLightProperties.getEntityProperties(params); - }); - - withReadLock([&] { requestedProperties += _ambientLightProperties.getEntityProperties(params); + requestedProperties += _skyboxProperties.getEntityProperties(params); }); + requestedProperties += _hazeProperties.getEntityProperties(params); + requestedProperties += _bloomProperties.getEntityProperties(params); requestedProperties += PROP_SHAPE_TYPE; requestedProperties += PROP_COMPOUND_SHAPE_URL; - withReadLock([&] { - requestedProperties += _skyboxProperties.getEntityProperties(params); - }); - requestedProperties += PROP_FLYING_ALLOWED; requestedProperties += PROP_GHOSTING_ALLOWED; requestedProperties += PROP_FILTER_URL; requestedProperties += PROP_HAZE_MODE; - requestedProperties += _hazeProperties.getEntityProperties(params); - requestedProperties += PROP_KEY_LIGHT_MODE; requestedProperties += PROP_AMBIENT_LIGHT_MODE; requestedProperties += PROP_SKYBOX_MODE; + requestedProperties += PROP_BLOOM_MODE; return requestedProperties; } @@ -235,44 +232,46 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - _ambientLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + _skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _bloomProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); - _skyboxProperties.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_HAZE_MODE, (uint32_t)getHazeMode()); - _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, - propertyFlags, propertiesDidntFit, propertyCount, appendState); - 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_BLOOM_MODE, (uint32_t)getBloomMode()); } 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::getComponentModeString(_hazeMode); - qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); - qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); - qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeString(_hazeMode); + qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); + qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); + qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeString(_bloomMode); _keyLightProperties.debugDump(); _ambientLightProperties.debugDump(); _skyboxProperties.debugDump(); _hazeProperties.debugDump(); + _bloomProperties.debugDump(); } ShapeType ZoneEntityItem::getShapeType() const { @@ -344,6 +343,7 @@ void ZoneEntityItem::resetRenderingPropertiesChanged() { _ambientLightPropertiesChanged = false; _skyboxPropertiesChanged = false; _hazePropertiesChanged = false; + _bloomPropertiesChanged = false; _stagePropertiesChanged = false; }); } @@ -359,6 +359,17 @@ 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; diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 0aaa32a57a..e2ebf16f11 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -18,6 +18,7 @@ #include "EntityTree.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include class ZoneEntityItem : public EntityItem { @@ -79,9 +80,13 @@ public: void setSkyboxMode(uint32_t value); uint32_t getSkyboxMode() const; + void setBloomMode(const uint32_t value); + uint32_t getBloomMode() const; + SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock([&] { return _skyboxProperties; }); } const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; } + const BloomPropertyGroup& getBloomProperties() const { return _bloomProperties; } bool getFlyingAllowed() const { return _flyingAllowed; } void setFlyingAllowed(bool value) { _flyingAllowed = value; } @@ -93,10 +98,8 @@ public: bool keyLightPropertiesChanged() const { return _keyLightPropertiesChanged; } bool ambientLightPropertiesChanged() const { return _ambientLightPropertiesChanged; } bool skyboxPropertiesChanged() const { return _skyboxPropertiesChanged; } - - bool hazePropertiesChanged() const { - return _hazePropertiesChanged; - } + bool hazePropertiesChanged() const { return _hazePropertiesChanged; } + bool bloomPropertiesChanged() const { return _bloomPropertiesChanged; } bool stagePropertiesChanged() const { return _stagePropertiesChanged; } @@ -133,9 +136,11 @@ protected: uint32_t _ambientLightMode { COMPONENT_MODE_INHERIT }; uint32_t _hazeMode { COMPONENT_MODE_INHERIT }; + uint32_t _bloomMode { COMPONENT_MODE_INHERIT }; SkyboxPropertyGroup _skyboxProperties; HazePropertyGroup _hazeProperties; + BloomPropertyGroup _bloomProperties; bool _flyingAllowed { DEFAULT_FLYING_ALLOWED }; bool _ghostingAllowed { DEFAULT_GHOSTING_ALLOWED }; @@ -146,6 +151,7 @@ protected: bool _ambientLightPropertiesChanged { false }; bool _skyboxPropertiesChanged { false }; bool _hazePropertiesChanged{ false }; + bool _bloomPropertiesChanged { false }; bool _stagePropertiesChanged { false }; static bool _drawZoneBoundaries; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 82e9820509..ae165af5d1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::ParticleSpin); + return static_cast(EntityVersion::BloomEffect); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 64c5bfe534..bfc92b9bde 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -240,7 +240,8 @@ enum class EntityVersion : PacketVersion { CollisionMask16Bytes, YieldSimulationOwnership, ParticleEntityFix, - ParticleSpin + ParticleSpin, + BloomEffect }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index e05f28ef0d..be61953073 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -14,6 +14,7 @@ #include "LightStage.h" #include "BackgroundStage.h" #include "HazeStage.h" +#include "BloomStage.h" #include #include #include "DeferredLightingEffect.h" @@ -22,6 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("LightStageSetup"); task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); + task.addJob("BloomStageSetup"); task.addJob("TransitionStageSetup"); task.addJob("HighlightStageSetup"); From 2959a406d767eaed3717211aa68330b14f093c54 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Aug 2018 18:18:58 -0700 Subject: [PATCH 2/3] working on enabling bloom --- .../src/RenderableZoneEntityItem.cpp | 49 ++++++ .../src/RenderableZoneEntityItem.h | 31 ++-- libraries/entities/src/BloomPropertyGroup.cpp | 159 +++++++++++++++++ libraries/entities/src/BloomPropertyGroup.h | 94 ++++++++++ .../entities/src/EntityItemProperties.cpp | 51 +++++- libraries/entities/src/EntityItemProperties.h | 4 + libraries/entities/src/EntityPropertyFlags.h | 5 + libraries/entities/src/ZoneEntityItem.cpp | 165 ++++++++++-------- libraries/entities/src/ZoneEntityItem.h | 14 +- libraries/graphics/src/graphics/Bloom.cpp | 18 ++ libraries/graphics/src/graphics/Bloom.h | 44 +++++ .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/render-utils/src/BloomEffect.cpp | 93 +++++----- libraries/render-utils/src/BloomEffect.h | 49 +----- libraries/render-utils/src/BloomStage.cpp | 80 +++++++++ libraries/render-utils/src/BloomStage.h | 122 +++++++++++++ libraries/render-utils/src/HazeStage.h | 1 - .../render-utils/src/RenderDeferredTask.cpp | 8 +- .../render-utils/src/UpdateSceneTask.cpp | 2 + libraries/render-utils/src/ZoneRenderer.cpp | 10 +- scripts/system/html/entityProperties.html | 46 +++++ scripts/system/html/js/entityProperties.js | 88 +++++++--- 23 files changed, 917 insertions(+), 221 deletions(-) create mode 100644 libraries/entities/src/BloomPropertyGroup.cpp create mode 100644 libraries/entities/src/BloomPropertyGroup.h create mode 100644 libraries/graphics/src/graphics/Bloom.cpp create mode 100644 libraries/graphics/src/graphics/Bloom.h create mode 100644 libraries/render-utils/src/BloomStage.cpp create mode 100644 libraries/render-utils/src/BloomStage.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index c5035431f6..f23e8096f1 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -64,6 +64,13 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity _hazeIndex = INVALID_INDEX; } } + + if (_bloomStage) { + if (!BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomStage->removeBloom(_bloomIndex); + _bloomIndex = INVALID_INDEX; + } + } } void ZoneEntityRenderer::doRender(RenderArgs* args) { @@ -112,6 +119,11 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { assert(_hazeStage); } + if (!_bloomStage) { + _bloomStage = args->_scene->getStage(); + assert(_bloomStage); + } + { // Sun // Need an update ? if (_needSunUpdate) { @@ -161,6 +173,15 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { } } + { + if (_needBloomUpdate) { + if (BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomIndex = _bloomStage->addBloom(_bloom); + } + _needBloomUpdate = false; + } + } + if (_visible) { // Finally, push the lights visible in the frame // @@ -190,6 +211,11 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { if (_hazeMode != COMPONENT_MODE_INHERIT) { _hazeStage->_currentFrame.pushHaze(_hazeIndex); } + + // Bloom only if the mode is not inherit, as the model deals with on/off + if (_bloomMode != COMPONENT_MODE_INHERIT) { + _bloomStage->_currentFrame.pushBloom(_bloomIndex); + } } } @@ -211,6 +237,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen bool ambientLightChanged = entity->ambientLightPropertiesChanged(); bool skyboxChanged = entity->skyboxPropertiesChanged(); bool hazeChanged = entity->hazePropertiesChanged(); + bool bloomChanged = entity->bloomPropertiesChanged(); entity->resetRenderingPropertiesChanged(); _lastPosition = entity->getWorldPosition(); @@ -221,6 +248,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen _ambientLightProperties = entity->getAmbientLightProperties(); _skyboxProperties = entity->getSkyboxProperties(); _hazeProperties = entity->getHazeProperties(); + _bloomProperties = entity->getBloomProperties(); #if 0 if (_lastShapeURL != _typedEntity->getCompoundShapeURL()) { @@ -258,6 +286,10 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen if (hazeChanged) { updateHazeFromEntity(entity); } + + if (bloomChanged) { + updateBloomFromEntity(entity); + } } void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { @@ -276,6 +308,7 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (entity->keyLightPropertiesChanged() || entity->ambientLightPropertiesChanged() || entity->hazePropertiesChanged() || + entity->bloomPropertiesChanged() || entity->skyboxPropertiesChanged()) { return true; @@ -388,6 +421,18 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) haze->setTransform(entity->getTransform().getMatrix()); } +void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity) { + setBloomMode((ComponentMode)entity->getBloomMode()); + + const auto& bloom = editBloom(); + + const uint32_t bloomMode = entity->getBloomMode(); + bloom->setBloomActive(bloomMode == COMPONENT_MODE_ENABLED); + bloom->setBloomIntensity(_bloomProperties.getBloomIntensity()); + bloom->setBloomThreshold(_bloomProperties.getBloomThreshold()); + bloom->setBloomSize(_bloomProperties.getBloomSize()); +} + void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer& entity) { setSkyboxMode((ComponentMode)entity->getSkyboxMode()); @@ -510,6 +555,10 @@ void ZoneEntityRenderer::setSkyboxMode(ComponentMode mode) { _skyboxMode = mode; } +void ZoneEntityRenderer::setBloomMode(ComponentMode mode) { + _bloomMode = mode; +} + void ZoneEntityRenderer::setSkyboxColor(const glm::vec3& color) { editSkybox()->setColor(color); } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index c48679e5d4..3e2690e1bd 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -1,7 +1,6 @@ // // RenderableZoneEntityItem.h // -// // Created by Clement on 4/22/15. // Copyright 2015 High Fidelity, Inc. // @@ -15,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "RenderableEntityItem.h" #include @@ -50,6 +51,7 @@ private: void updateAmbientLightFromEntity(const TypedEntityPointer& entity); void updateHazeFromEntity(const TypedEntityPointer& entity); void updateKeyBackgroundFromEntity(const TypedEntityPointer& entity); + void updateBloomFromEntity(const TypedEntityPointer& entity); void updateAmbientMap(); void updateSkyboxMap(); void setAmbientURL(const QString& ambientUrl); @@ -59,6 +61,7 @@ private: void setKeyLightMode(ComponentMode mode); void setAmbientLightMode(ComponentMode mode); void setSkyboxMode(ComponentMode mode); + void setBloomMode(ComponentMode mode); void setSkyboxColor(const glm::vec3& color); void setProceduralUserData(const QString& userData); @@ -68,6 +71,7 @@ private: graphics::SunSkyStagePointer editBackground() { _needBackgroundUpdate = true; return _background; } graphics::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); } graphics::HazePointer editHaze() { _needHazeUpdate = true; return _haze; } + graphics::BloomPointer editBloom() { _needBloomUpdate = true; return _bloom; } glm::vec3 _lastPosition; glm::vec3 _lastDimensions; @@ -82,36 +86,43 @@ private: #endif LightStagePointer _stage; - const graphics::LightPointer _sunLight{ std::make_shared() }; - const graphics::LightPointer _ambientLight{ std::make_shared() }; - const graphics::SunSkyStagePointer _background{ std::make_shared() }; - const graphics::HazePointer _haze{ std::make_shared() }; + const graphics::LightPointer _sunLight { std::make_shared() }; + const graphics::LightPointer _ambientLight { std::make_shared() }; + const graphics::SunSkyStagePointer _background { std::make_shared() }; + const graphics::HazePointer _haze { std::make_shared() }; + const graphics::BloomPointer _bloom { std::make_shared() }; 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 }; - indexed_container::Index _sunIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _shadowIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _ambientIndex{ LightStage::INVALID_INDEX }; + indexed_container::Index _sunIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _shadowIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _ambientIndex { LightStage::INVALID_INDEX }; BackgroundStagePointer _backgroundStage; - BackgroundStage::Index _backgroundIndex{ BackgroundStage::INVALID_INDEX }; + BackgroundStage::Index _backgroundIndex { BackgroundStage::INVALID_INDEX }; HazeStagePointer _hazeStage; - HazeStage::Index _hazeIndex{ HazeStage::INVALID_INDEX }; + HazeStage::Index _hazeIndex { HazeStage::INVALID_INDEX }; + + BloomStagePointer _bloomStage; + BloomStage::Index _bloomIndex { BloomStage::INVALID_INDEX }; bool _needUpdate{ true }; bool _needSunUpdate{ true }; bool _needAmbientUpdate{ true }; bool _needBackgroundUpdate{ true }; bool _needHazeUpdate{ true }; + bool _needBloomUpdate { true }; KeyLightPropertyGroup _keyLightProperties; AmbientLightPropertyGroup _ambientLightProperties; HazePropertyGroup _hazeProperties; SkyboxPropertyGroup _skyboxProperties; + BloomPropertyGroup _bloomProperties; // More attributes used for rendering: QString _ambientTextureURL; diff --git a/libraries/entities/src/BloomPropertyGroup.cpp b/libraries/entities/src/BloomPropertyGroup.cpp new file mode 100644 index 0000000000..2c4d46ab35 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.cpp @@ -0,0 +1,159 @@ +// +// BloomPropertyGroup.cpp +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "BloomPropertyGroup.h" + +#include + +#include "EntityItemProperties.h" +#include "EntityItemPropertiesMacros.h" + +void BloomPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); +} + +void BloomPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomIntensity, float, setBloomIntensity); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomThreshold, float, setBloomThreshold); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomSize, float, setBloomSize); +} + +void BloomPropertyGroup::merge(const BloomPropertyGroup& other) { + COPY_PROPERTY_IF_CHANGED(bloomIntensity); + COPY_PROPERTY_IF_CHANGED(bloomThreshold); + COPY_PROPERTY_IF_CHANGED(bloomSize); +} + +void BloomPropertyGroup::debugDump() const { + qCDebug(entities) << " BloomPropertyGroup: ---------------------------------------------"; + qCDebug(entities) << " _bloomIntensity:" << _bloomIntensity; + qCDebug(entities) << " _bloomThreshold:" << _bloomThreshold; + qCDebug(entities) << " _bloomSize:" << _bloomSize; +} + +void BloomPropertyGroup::listChangedProperties(QList& out) { + if (bloomIntensityChanged()) { + out << "bloom-bloomIntensity"; + } + if (bloomThresholdChanged()) { + out << "bloom-bloomThreshold"; + } + if (bloomSizeChanged()) { + out << "bloom-bloomSize"; + } +} + +bool BloomPropertyGroup::appendToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); + + return true; +} + +bool BloomPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) { + int bytesRead = 0; + bool overwriteLocalData = true; + bool somethingChanged = false; + + READ_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_INTENSITY, BloomIntensity); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_THRESHOLD, BloomThreshold); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_SIZE, BloomSize); + + processedBytes += bytesRead; + + Q_UNUSED(somethingChanged); + + return true; +} + +void BloomPropertyGroup::markAllChanged() { + _bloomIntensityChanged = true; + _bloomThresholdChanged = true; + _bloomSizeChanged = true; +} + +EntityPropertyFlags BloomPropertyGroup::getChangedProperties() const { + EntityPropertyFlags changedProperties; + + CHECK_PROPERTY_CHANGE(PROP_BLOOM_INTENSITY, bloomIntensity); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_THRESHOLD, bloomThreshold); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_SIZE, bloomSize); + + return changedProperties; +} + +void BloomPropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomIntensity, getBloomIntensity); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomThreshold, getBloomThreshold); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomSize, getBloomSize); +} + +bool BloomPropertyGroup::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomIntensity, bloomIntensity, setBloomIntensity); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomThreshold, bloomThreshold, setBloomThreshold); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomSize, bloomSize, setBloomSize); + + return somethingChanged; +} + +EntityPropertyFlags BloomPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties; + + requestedProperties += PROP_BLOOM_INTENSITY; + requestedProperties += PROP_BLOOM_THRESHOLD; + requestedProperties += PROP_BLOOM_SIZE; + + return requestedProperties; +} + +void BloomPropertyGroup::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_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); +} + +int BloomPropertyGroup::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_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + return bytesRead; +} diff --git a/libraries/entities/src/BloomPropertyGroup.h b/libraries/entities/src/BloomPropertyGroup.h new file mode 100644 index 0000000000..a1f9b6d748 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.h @@ -0,0 +1,94 @@ +// +// BloomPropertyGroup.h +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_BloomPropertyGroup_h +#define hifi_BloomPropertyGroup_h + +#include +#include + +#include + +#include "PropertyGroup.h" +#include "EntityItemPropertiesMacros.h" + +class EntityItemProperties; +class EncodeBitstreamParams; +class OctreePacketData; +class EntityTreeElementExtraEncodeData; +class ReadBitstreamToTreeParams; + +static const float INITIAL_BLOOM_INTENSITY { 0.25f }; +static const float INITIAL_BLOOM_THRESHOLD { 0.7f }; +static const float INITIAL_BLOOM_SIZE { 0.9f }; + +/**jsdoc + * Bloom is defined by the following properties. + * @typedef {object} Entities.Bloom + * + * @property {number} bloomIntensity=0.25 - The intensity of the bloom effect. + * @property {number} bloomThreshold=0.7 - The threshold for the bloom effect. + * @property {number} bloomSize=0.9 - The size of the bloom effect. + */ +class BloomPropertyGroup : public PropertyGroup { +public: + // EntityItemProperty related helpers + virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, + QScriptEngine* engine, bool skipDefaults, + EntityItemProperties& defaultEntityProperties) const override; + virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) override; + + void merge(const BloomPropertyGroup& other); + + virtual void debugDump() const override; + virtual void listChangedProperties(QList& 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(PROP_BLOOM_INTENSITY, BloomIntensity, bloomIntensity, float, INITIAL_BLOOM_INTENSITY); + DEFINE_PROPERTY(PROP_BLOOM_THRESHOLD, BloomThreshold, bloomThreshold, float, INITIAL_BLOOM_THRESHOLD); + DEFINE_PROPERTY(PROP_BLOOM_SIZE, BloomSize, bloomSize, float, INITIAL_BLOOM_SIZE); + +}; + +#endif // hifi_BloomPropertyGroup_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1f9bf2eb18..68d0e6aed4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -37,6 +37,7 @@ AnimationPropertyGroup EntityItemProperties::_staticAnimation; SkyboxPropertyGroup EntityItemProperties::_staticSkybox; HazePropertyGroup EntityItemProperties::_staticHaze; +BloomPropertyGroup EntityItemProperties::_staticBloom; KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; AmbientLightPropertyGroup EntityItemProperties::_staticAmbientLight; @@ -84,6 +85,7 @@ void EntityItemProperties::debugDump() const { getHaze().debugDump(); getKeyLight().debugDump(); getAmbientLight().debugDump(); + getBloom().debugDump(); qCDebug(entities) << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); @@ -211,6 +213,10 @@ QString EntityItemProperties::getHazeModeAsString() const { return getComponentModeAsString(_hazeMode); } +QString EntityItemProperties::getBloomModeAsString() const { + return getComponentModeAsString(_bloomMode); +} + QString EntityItemProperties::getComponentModeString(uint32_t mode) { // return "inherit" if mode is not valid if (mode < COMPONENT_MODE_ITEM_COUNT) { @@ -235,6 +241,15 @@ void EntityItemProperties::setHazeModeFromString(const QString& hazeMode) { } } +void EntityItemProperties::setBloomModeFromString(const QString& bloomMode) { + auto result = findComponent(bloomMode); + + if (result != COMPONENT_MODES.end()) { + _bloomMode = result->first; + _bloomModeChanged = true; + } +} + QString EntityItemProperties::getKeyLightModeAsString() const { return getComponentModeAsString(_keyLightMode); } @@ -394,6 +409,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEY_LIGHT_MODE, keyLightMode); CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_MODE, bloomMode); CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); @@ -454,6 +470,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { changedProperties += _ambientLight.getChangedProperties(); changedProperties += _skybox.getChangedProperties(); changedProperties += _haze.getChangedProperties(); + changedProperties += _bloom.getChangedProperties(); return changedProperties; } @@ -1164,6 +1181,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * "enabled": The haze properties of this zone are enabled, overriding the haze from any enclosing zone. * @property {Entities.Haze} haze - The haze properties of the zone. * + * @property {string} bloomMode="inherit" - Configures the bloom in the zone. Possible values:
+ * "inherit": The bloom from any enclosing zone continues into this zone.
+ * "disabled": The bloom from any enclosing zone and the bloom of this zone are disabled in this zone.
+ * "enabled": The bloom properties of this zone are enabled, overriding the bloom from any enclosing zone. + * @property {Entities.Bloom} bloom - The bloom properties of the zone. + * * @property {boolean} flyingAllowed=true - If true then visitors can fly in the zone; otherwise they cannot. * @property {boolean} ghostingAllowed=true - If true then visitors with avatar collisions turned off will not * collide with content in the zone; otherwise visitors will always collide with content in the zone. @@ -1382,6 +1405,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString()); _haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString()); + _bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); @@ -1630,6 +1656,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(keyLightMode, KeyLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(bloomMode, BloomMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, vec3, setVoxelVolumeSize); @@ -1662,6 +1689,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool _ambientLight.copyFromScriptValue(object, _defaultSettings); _skybox.copyFromScriptValue(object, _defaultSettings); _haze.copyFromScriptValue(object, _defaultSettings); + _bloom.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(xTextureURL, QString, setXTextureURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL); @@ -1803,6 +1831,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(keyLightMode); COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); + COPY_PROPERTY_IF_CHANGED(bloomMode); COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); @@ -1825,6 +1854,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { _ambientLight.merge(other._ambientLight); _skybox.merge(other._skybox); _haze.merge(other._haze); + _bloom.merge(other._bloom); COPY_PROPERTY_IF_CHANGED(xTextureURL); COPY_PROPERTY_IF_CHANGED(yTextureURL); @@ -2096,6 +2126,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_RANGE, Haze, haze, HazeKeyLightRange, hazeKeyLightRange); ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_ALTITUDE, Haze, haze, HazeKeyLightAltitude, hazeKeyLightAltitude); + ADD_PROPERTY_TO_MAP(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); + ADD_PROPERTY_TO_MAP(PROP_KEY_LIGHT_MODE, KeyLightMode, keyLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t); @@ -2357,6 +2392,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticHaze.setProperties(properties); _staticHaze.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode()); + _staticBloom.setProperties(properties); + _staticBloom.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)properties.getKeyLightMode()); APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)properties.getAmbientLightMode()); APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)properties.getSkyboxMode()); @@ -2731,6 +2770,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HAZE_MODE, uint32_t, setHazeMode); properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode); + properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); @@ -3044,10 +3086,12 @@ void EntityItemProperties::markAllChanged() { _skyboxModeChanged = true; _ambientLightModeChanged = true; _hazeModeChanged = true; + _bloomModeChanged = true; _animation.markAllChanged(); _skybox.markAllChanged(); _haze.markAllChanged(); + _bloom.markAllChanged(); _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; @@ -3442,15 +3486,15 @@ QList EntityItemProperties::listChangedProperties() { if (hazeModeChanged()) { out += "hazeMode"; } - + if (bloomModeChanged()) { + out += "bloomMode"; + } if (keyLightModeChanged()) { out += "keyLightMode"; } - if (ambientLightModeChanged()) { out += "ambientLightMode"; } - if (skyboxModeChanged()) { out += "skyboxMode"; } @@ -3581,6 +3625,7 @@ QList EntityItemProperties::listChangedProperties() { getAmbientLight().listChangedProperties(out); getSkybox().listChangedProperties(out); getHaze().listChangedProperties(out); + getBloom().listChangedProperties(out); return out; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 04e54c54a5..50305345de 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -42,6 +42,7 @@ #include "SimulationOwner.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include "TextEntityItem.h" #include "ZoneEntityItem.h" @@ -195,9 +196,11 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); + DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup); DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); + DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); @@ -533,6 +536,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, KeyLightMode, keyLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientLightMode, ambientLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, SkyboxMode, skyboxMode, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, BloomMode, bloomMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cloneable, cloneable, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, CloneLifetime, cloneLifetime, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 156c5d9dd4..3932730661 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -257,6 +257,11 @@ enum EntityPropertyList { PROP_SPIN_SPREAD, PROP_PARTICLE_ROTATE_WITH_ENTITY, + PROP_BLOOM_MODE, + PROP_BLOOM_INTENSITY, + PROP_BLOOM_THRESHOLD, + PROP_BLOOM_SIZE, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index f2550e5d3c..a7dfa1a41e 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -47,33 +47,27 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - // Contains a QString property, must be synchronized + // Contain QString properties, must be synchronized withReadLock([&] { _keyLightProperties.getProperties(properties); - }); - - withReadLock([&] { _ambientLightProperties.getProperties(properties); + _skyboxProperties.getProperties(properties); }); + _hazeProperties.getProperties(properties); + _bloomProperties.getProperties(properties); COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); - // Contains a QString property, must be synchronized - withReadLock([&] { - _skyboxProperties.getProperties(properties); - }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(filterURL, getFilterURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(hazeMode, getHazeMode); - _hazeProperties.getProperties(properties); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightMode, getKeyLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientLightMode, getAmbientLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(skyboxMode, getSkyboxMode); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(bloomMode, getBloomMode); return properties; } @@ -102,32 +96,27 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie // Contains a QString property, must be synchronized withWriteLock([&] { _keyLightPropertiesChanged = _keyLightProperties.setProperties(properties); - }); - withWriteLock([&] { _ambientLightPropertiesChanged = _ambientLightProperties.setProperties(properties); + _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); }); + _hazePropertiesChanged = _hazeProperties.setProperties(properties); + _bloomPropertiesChanged = _bloomProperties.setProperties(properties); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); - // Contains a QString property, must be synchronized - withWriteLock([&] { - _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); - }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(filterURL, setFilterURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(hazeMode, setHazeMode); - _hazePropertiesChanged = _hazeProperties.setProperties(properties); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightMode, setKeyLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientLightMode, setAmbientLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(skyboxMode, setSkyboxMode); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(bloomMode, setBloomMode); somethingChanged = somethingChanged || _keyLightPropertiesChanged || _ambientLightPropertiesChanged || - _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged; + _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged || _bloomPropertiesChanged; return somethingChanged; } @@ -139,54 +128,67 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - int bytesFromKeylight; - withWriteLock([&] { - bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); - }); + { + int bytesFromKeylight; + withWriteLock([&] { + bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _keyLightPropertiesChanged; + bytesRead += bytesFromKeylight; + dataAt += bytesFromKeylight; + } - somethingChanged = somethingChanged || _keyLightPropertiesChanged; - bytesRead += bytesFromKeylight; - dataAt += bytesFromKeylight; + { + int bytesFromAmbientlight; + withWriteLock([&] { + bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _ambientLightPropertiesChanged; + bytesRead += bytesFromAmbientlight; + dataAt += bytesFromAmbientlight; + } - int bytesFromAmbientlight; - withWriteLock([&] { - bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); - }); + { + int bytesFromSkybox; + withWriteLock([&] { + bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); + }); + somethingChanged = somethingChanged || _skyboxPropertiesChanged; + bytesRead += bytesFromSkybox; + dataAt += bytesFromSkybox; + } - somethingChanged = somethingChanged || _ambientLightPropertiesChanged; - bytesRead += bytesFromAmbientlight; - dataAt += bytesFromAmbientlight; + { + int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _hazePropertiesChanged); + somethingChanged = somethingChanged || _hazePropertiesChanged; + bytesRead += bytesFromHaze; + dataAt += bytesFromHaze; + } + + { + int bytesFromBloom = _bloomProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _bloomPropertiesChanged); + somethingChanged = somethingChanged || _bloomPropertiesChanged; + bytesRead += bytesFromBloom; + dataAt += bytesFromBloom; + } READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); - int bytesFromSkybox; - withWriteLock([&] { - bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); - }); - somethingChanged = somethingChanged || _skyboxPropertiesChanged; - bytesRead += bytesFromSkybox; - dataAt += bytesFromSkybox; - READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed); READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed); READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL); READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint32_t, setHazeMode); - - int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _hazePropertiesChanged); - - somethingChanged = somethingChanged || _hazePropertiesChanged; - bytesRead += bytesFromHaze; - dataAt += bytesFromHaze; - READ_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); + READ_ENTITY_PROPERTY(PROP_BLOOM_MODE, uint32_t, setBloomMode); return bytesRead; } @@ -196,29 +198,24 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p withReadLock([&] { requestedProperties += _keyLightProperties.getEntityProperties(params); - }); - - withReadLock([&] { requestedProperties += _ambientLightProperties.getEntityProperties(params); + requestedProperties += _skyboxProperties.getEntityProperties(params); }); + requestedProperties += _hazeProperties.getEntityProperties(params); + requestedProperties += _bloomProperties.getEntityProperties(params); requestedProperties += PROP_SHAPE_TYPE; requestedProperties += PROP_COMPOUND_SHAPE_URL; - withReadLock([&] { - requestedProperties += _skyboxProperties.getEntityProperties(params); - }); - requestedProperties += PROP_FLYING_ALLOWED; requestedProperties += PROP_GHOSTING_ALLOWED; requestedProperties += PROP_FILTER_URL; requestedProperties += PROP_HAZE_MODE; - requestedProperties += _hazeProperties.getEntityProperties(params); - requestedProperties += PROP_KEY_LIGHT_MODE; requestedProperties += PROP_AMBIENT_LIGHT_MODE; requestedProperties += PROP_SKYBOX_MODE; + requestedProperties += PROP_BLOOM_MODE; return requestedProperties; } @@ -235,44 +232,46 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - _ambientLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + _skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _bloomProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); - _skyboxProperties.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_HAZE_MODE, (uint32_t)getHazeMode()); - _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, - propertyFlags, propertiesDidntFit, propertyCount, appendState); - 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_BLOOM_MODE, (uint32_t)getBloomMode()); } 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::getComponentModeString(_hazeMode); - qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); - qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); - qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeString(_hazeMode); + qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); + qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); + qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeString(_bloomMode); _keyLightProperties.debugDump(); _ambientLightProperties.debugDump(); _skyboxProperties.debugDump(); _hazeProperties.debugDump(); + _bloomProperties.debugDump(); } ShapeType ZoneEntityItem::getShapeType() const { @@ -344,6 +343,7 @@ void ZoneEntityItem::resetRenderingPropertiesChanged() { _ambientLightPropertiesChanged = false; _skyboxPropertiesChanged = false; _hazePropertiesChanged = false; + _bloomPropertiesChanged = false; _stagePropertiesChanged = false; }); } @@ -359,6 +359,17 @@ 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; diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 0aaa32a57a..e2ebf16f11 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -18,6 +18,7 @@ #include "EntityTree.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include class ZoneEntityItem : public EntityItem { @@ -79,9 +80,13 @@ public: void setSkyboxMode(uint32_t value); uint32_t getSkyboxMode() const; + void setBloomMode(const uint32_t value); + uint32_t getBloomMode() const; + SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock([&] { return _skyboxProperties; }); } const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; } + const BloomPropertyGroup& getBloomProperties() const { return _bloomProperties; } bool getFlyingAllowed() const { return _flyingAllowed; } void setFlyingAllowed(bool value) { _flyingAllowed = value; } @@ -93,10 +98,8 @@ public: bool keyLightPropertiesChanged() const { return _keyLightPropertiesChanged; } bool ambientLightPropertiesChanged() const { return _ambientLightPropertiesChanged; } bool skyboxPropertiesChanged() const { return _skyboxPropertiesChanged; } - - bool hazePropertiesChanged() const { - return _hazePropertiesChanged; - } + bool hazePropertiesChanged() const { return _hazePropertiesChanged; } + bool bloomPropertiesChanged() const { return _bloomPropertiesChanged; } bool stagePropertiesChanged() const { return _stagePropertiesChanged; } @@ -133,9 +136,11 @@ protected: uint32_t _ambientLightMode { COMPONENT_MODE_INHERIT }; uint32_t _hazeMode { COMPONENT_MODE_INHERIT }; + uint32_t _bloomMode { COMPONENT_MODE_INHERIT }; SkyboxPropertyGroup _skyboxProperties; HazePropertyGroup _hazeProperties; + BloomPropertyGroup _bloomProperties; bool _flyingAllowed { DEFAULT_FLYING_ALLOWED }; bool _ghostingAllowed { DEFAULT_GHOSTING_ALLOWED }; @@ -146,6 +151,7 @@ protected: bool _ambientLightPropertiesChanged { false }; bool _skyboxPropertiesChanged { false }; bool _hazePropertiesChanged{ false }; + bool _bloomPropertiesChanged { false }; bool _stagePropertiesChanged { false }; static bool _drawZoneBoundaries; diff --git a/libraries/graphics/src/graphics/Bloom.cpp b/libraries/graphics/src/graphics/Bloom.cpp new file mode 100644 index 0000000000..f8dcda3292 --- /dev/null +++ b/libraries/graphics/src/graphics/Bloom.cpp @@ -0,0 +1,18 @@ +// +// Bloom.cpp +// libraries/graphics/src/graphics +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Bloom.h" + +using namespace graphics; + +const float Bloom::INITIAL_BLOOM_INTENSITY { 0.25f }; +const float Bloom::INITIAL_BLOOM_THRESHOLD { 0.7f }; +const float Bloom::INITIAL_BLOOM_SIZE { 0.9f }; \ No newline at end of file diff --git a/libraries/graphics/src/graphics/Bloom.h b/libraries/graphics/src/graphics/Bloom.h new file mode 100644 index 0000000000..02362ce25d --- /dev/null +++ b/libraries/graphics/src/graphics/Bloom.h @@ -0,0 +1,44 @@ +// +// Bloom.h +// libraries/graphics/src/graphics +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Bloom_h +#define hifi_model_Bloom_h + +#include + +namespace graphics { + class Bloom { + public: + // Initial values + static const float INITIAL_BLOOM_INTENSITY; + static const float INITIAL_BLOOM_THRESHOLD; + static const float INITIAL_BLOOM_SIZE; + + Bloom() {} + + void setBloomIntensity(const float bloomIntensity) { _bloomIntensity = bloomIntensity; } + void setBloomThreshold(const float bloomThreshold) { _bloomThreshold = bloomThreshold; } + void setBloomSize(const float bloomSize) { _bloomSize = bloomSize; } + void setBloomActive(const bool isBloomActive) { _isBloomActive = isBloomActive; } + + float getBloomIntensity() { return _bloomIntensity; } + float getBloomThreshold() { return _bloomThreshold; } + float getBloomSize() { return _bloomSize; } + bool getBloomActive() { return _isBloomActive; } + + private: + bool _isBloomActive { false }; + float _bloomIntensity { INITIAL_BLOOM_INTENSITY }; + float _bloomThreshold {INITIAL_BLOOM_THRESHOLD }; + float _bloomSize { INITIAL_BLOOM_SIZE }; + }; + using BloomPointer = std::shared_ptr; +} +#endif // hifi_model_Bloom_h diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 82e9820509..ae165af5d1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::ParticleSpin); + return static_cast(EntityVersion::BloomEffect); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 64c5bfe534..bfc92b9bde 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -240,7 +240,8 @@ enum class EntityVersion : PacketVersion { CollisionMask16Bytes, YieldSimulationOwnership, ParticleEntityFix, - ParticleSpin + ParticleSpin, + BloomEffect }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 2a9a9b3850..91ba95f3af 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -25,11 +25,7 @@ BloomThreshold::BloomThreshold(unsigned int downsamplingFactor) { _parameters.edit()._sampleCount = downsamplingFactor; } -void BloomThreshold::configure(const Config& config) { - if (_parameters.get()._threshold != config.threshold) { - _parameters.edit()._threshold = config.threshold; - } -} +void BloomThreshold::configure(const Config& config) {} void BloomThreshold::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); @@ -39,6 +35,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons const auto frameTransform = inputs.get0(); const auto inputFrameBuffer = inputs.get1(); + const auto bloom = inputs.get2(); assert(inputFrameBuffer->hasColor()); @@ -68,6 +65,28 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; + if (!bloom || !bloom->getBloomActive()) { + outputs = _outputBuffer; + return; + } + + _parameters.edit()._threshold = bloom->getBloomThreshold(); + + //{ + // std::string blurName { "BloomBlurN" }; + // auto sigma = 0.5f + bloom->getBloomSize() * 3.5f; + // auto task = static_cast(this); + + // for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { + // blurName.back() = '0' + i; + // auto blurJobIt = task->editJob(blurName); + // assert(blurJobIt != task->_jobs.end()); + // auto& gaussianBlur = blurJobIt->edit(); + // auto gaussianBlurParams = gaussianBlur.getParameters(); + // gaussianBlurParams->setFilterGaussianTaps(9, sigma); + // } + //} + gpu::doInBatch("BloomThreshold::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -90,16 +109,7 @@ BloomApply::BloomApply() { } -void BloomApply::configure(const Config& config) { - const auto newIntensity = config.intensity / 3.0f; - - if (_parameters.get()._intensities.x != newIntensity) { - auto& parameters = _parameters.edit(); - parameters._intensities.x = newIntensity; - parameters._intensities.y = newIntensity; - parameters._intensities.z = newIntensity; - } -} +void BloomApply::configure(const Config& config) {} void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); @@ -123,8 +133,19 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In const auto blur0FB = inputs.get1(); const auto blur1FB = inputs.get2(); const auto blur2FB = inputs.get3(); + const auto bloom = inputs.get4(); const glm::ivec4 viewport{ 0, 0, framebufferSize.x, framebufferSize.y }; + if (!bloom || !bloom->getBloomActive()) { + return; + } + + const auto newIntensity = bloom->getBloomIntensity() / 3.0f; + auto& parameters = _parameters.edit(); + parameters._intensities.x = newIntensity; + parameters._intensities.y = newIntensity; + parameters._intensities.z = newIntensity; + gpu::doInBatch("BloomApply::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -266,43 +287,9 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In }); } -void BloomConfig::setIntensity(float value) { - auto task = static_cast(_task); - auto blurJobIt = task->editJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - blurJobIt->getConfiguration()->setProperty("intensity", value); -} +BloomEffect::BloomEffect() {} -float BloomConfig::getIntensity() const { - auto task = static_cast(_task); - auto blurJobIt = task->getJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - return blurJobIt->getConfiguration()->property("intensity").toFloat(); -} - -void BloomConfig::setSize(float value) { - std::string blurName{ "BloomBlurN" }; - auto sigma = 0.5f+value*3.5f; - auto task = static_cast(_task); - - for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { - blurName.back() = '0' + i; - auto blurJobIt = task->editJob(blurName); - assert(blurJobIt != task->_jobs.end()); - auto& gaussianBlur = blurJobIt->edit(); - auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps(9, sigma); - } - auto blurJobIt = task->getJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - blurJobIt->getConfiguration()->setProperty("sigma", sigma); -} - -Bloom::Bloom() { - -} - -void Bloom::configure(const Config& config) { +void BloomEffect::configure(const Config& config) { std::string blurName{ "BloomBlurN" }; for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { @@ -312,7 +299,7 @@ void Bloom::configure(const Config& config) { } } -void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { +void BloomEffect::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { // Start by computing threshold of color buffer input at quarter resolution const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs, 4U); @@ -325,7 +312,7 @@ void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying const auto& frameBuffer = input[1]; // Mix all blur levels at quarter resolution - const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying(); + const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2, input.get2()).asVarying(); task.addJob("BloomApply", applyInput); // And then blend result in additive manner on top of final color buffer const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying(); diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 04cb4a9474..150a134dac 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -14,42 +14,21 @@ #include +#include "graphics/Bloom.h" + #include "DeferredFrameTransform.h" class BloomConfig : public render::Task::Config { Q_OBJECT - Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity NOTIFY dirty) - Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) - -public: - - BloomConfig() : render::Task::Config(false) {} - - float size{ 0.7f }; - - void setIntensity(float value); - float getIntensity() const; - void setSize(float value); - -signals: - void dirty(); }; class BloomThresholdConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) - -public: - - float threshold{ 0.9f }; - -signals: - void dirty(); }; class BloomThreshold { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using Outputs = gpu::FramebufferPointer; using Config = BloomThresholdConfig; using JobModel = render::Job::ModelIO; @@ -71,21 +50,11 @@ private: class BloomApplyConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) - Q_PROPERTY(float sigma MEMBER sigma NOTIFY dirty) - -public: - - float intensity{ 0.25f }; - float sigma{ 1.0f }; - -signals: - void dirty(); }; class BloomApply { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet5; using Config = BloomApplyConfig; using JobModel = render::Job::ModelI; @@ -118,7 +87,7 @@ private: class DebugBloomConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) + Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) public: @@ -155,13 +124,13 @@ private: DebugBloomConfig::Mode _mode; }; -class Bloom { +class BloomEffect { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using Config = BloomConfig; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelI; - Bloom(); + BloomEffect(); void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); diff --git a/libraries/render-utils/src/BloomStage.cpp b/libraries/render-utils/src/BloomStage.cpp new file mode 100644 index 0000000000..9a1c8ee183 --- /dev/null +++ b/libraries/render-utils/src/BloomStage.cpp @@ -0,0 +1,80 @@ +// +// BloomStage.cpp +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "BloomStage.h" + +#include "DeferredLightingEffect.h" + +#include + +std::string BloomStage::_stageName { "BLOOM_STAGE"}; +const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + +FetchBloomStage::FetchBloomStage() { + _bloom = std::make_shared(); +} + +void FetchBloomStage::configure(const Config& config) { + _bloom->setBloomIntensity(config.bloomIntensity); + _bloom->setBloomThreshold(config.bloomThreshold); + _bloom->setBloomSize(config.bloomSize); + _bloom->setBloomActive(config.isBloomActive); +} + +BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const { + auto found = _bloomMap.find(bloom); + if (found != _bloomMap.end()) { + return INVALID_INDEX; + } else { + return (*found).second; + } +} + +BloomStage::Index BloomStage::addBloom(const BloomPointer& bloom) { + auto found = _bloomMap.find(bloom); + if (found == _bloomMap.end()) { + auto bloomId = _blooms.newElement(bloom); + // Avoid failing to allocate a bloom, just pass + if (bloomId != INVALID_INDEX) { + // Insert the bloom and its index in the reverse map + _bloomMap.insert(BloomMap::value_type(bloom, bloomId)); + } + return bloomId; + } else { + return (*found).second; + } +} + +BloomStage::BloomPointer BloomStage::removeBloom(Index index) { + BloomPointer removed = _blooms.freeElement(index); + if (removed) { + _bloomMap.erase(removed); + } + return removed; +} + +BloomStageSetup::BloomStageSetup() {} + +void BloomStageSetup::run(const render::RenderContextPointer& renderContext) { + auto stage = renderContext->_scene->getStage(BloomStage::getName()); + if (!stage) { + renderContext->_scene->resetStage(BloomStage::getName(), std::make_shared()); + } +} + +void FetchBloomStage::run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom) { + auto bloomStage = renderContext->_scene->getStage(); + assert(bloomStage); + + bloom = nullptr; + if (bloomStage->_currentFrame._blooms.size() != 0) { + auto bloomId = bloomStage->_currentFrame._blooms.front(); + bloom = bloomStage->getBloom(bloomId); + } +} diff --git a/libraries/render-utils/src/BloomStage.h b/libraries/render-utils/src/BloomStage.h new file mode 100644 index 0000000000..76829a19a6 --- /dev/null +++ b/libraries/render-utils/src/BloomStage.h @@ -0,0 +1,122 @@ +// +// BloomStage.h + +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_utils_BloomStage_h +#define hifi_render_utils_BloomStage_h + +#include +#include +#include +#include +#include + +#include +#include +#include + +// Bloom stage to set up bloom-related rendering tasks +class BloomStage : 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 BloomPointer = graphics::BloomPointer; + using Blooms = render::indexed_container::IndexedPointerVector; + using BloomMap = std::unordered_map; + + using BloomIndices = std::vector; + + Index findBloom(const BloomPointer& bloom) const; + Index addBloom(const BloomPointer& bloom); + + BloomPointer removeBloom(Index index); + + bool checkBloomId(Index index) const { return _blooms.checkIndex(index); } + + Index getNumBlooms() const { return _blooms.getNumElements(); } + Index getNumFreeBlooms() const { return _blooms.getNumFreeIndices(); } + Index getNumAllocatedBlooms() const { return _blooms.getNumAllocatedIndices(); } + + BloomPointer getBloom(Index bloomId) const { + return _blooms.get(bloomId); + } + + Blooms _blooms; + BloomMap _bloomMap; + + class Frame { + public: + Frame() {} + + void clear() { _blooms.clear(); } + + void pushBloom(BloomStage::Index index) { _blooms.emplace_back(index); } + + BloomStage::BloomIndices _blooms; + }; + + Frame _currentFrame; +}; +using BloomStagePointer = std::shared_ptr; + +class BloomStageSetup { +public: + using JobModel = render::Job::Model; + + BloomStageSetup(); + void run(const render::RenderContextPointer& renderContext); + +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); + Q_PROPERTY(bool isBloomActive MEMBER isBloomActive WRITE setBloomActive 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 }; + + bool isBloomActive { false }; + +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(); } + void setBloomActive(const bool active) { isBloomActive = active; emit dirty(); } + +signals: + void dirty(); +}; + +class FetchBloomStage { +public: + using Config = FetchBloomConfig; + using JobModel = render::Job::ModelO; + + FetchBloomStage(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom); + +private: + graphics::BloomPointer _bloom; +}; +#endif diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 8f137cb280..b48168e376 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -163,6 +163,5 @@ public: private: graphics::HazePointer _haze; - gpu::PipelinePointer _hazePipeline; }; #endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 59c86acd19..b71d712a6e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -45,6 +45,7 @@ #include "TextureCache.h" #include "ZoneRenderer.h" #include "FadeEffect.h" +#include "BloomStage.h" #include "RenderUtilsLogging.h" #include "AmbientOcclusionEffect.h" @@ -171,7 +172,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto velocityBufferOutputs = task.addJob("VelocityBuffer", velocityBufferInputs); const auto velocityBuffer = velocityBufferOutputs.getN(0); - // Clear Light, Haze and Skybox Stages and render zones from the general metas bucket + // Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket const auto zones = task.addJob("ZoneRenderer", metas); // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. @@ -240,8 +241,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("Antialiasing", antialiasingInputs); // Add bloom - const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying(); - task.addJob("Bloom", bloomInputs); + const auto bloomModel = task.addJob("BloomModel"); + const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomModel).asVarying(); + task.addJob("Bloom", bloomInputs); // Lighting Buffer ready for tone mapping const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying(); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index e05f28ef0d..be61953073 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -14,6 +14,7 @@ #include "LightStage.h" #include "BackgroundStage.h" #include "HazeStage.h" +#include "BloomStage.h" #include #include #include "DeferredLightingEffect.h" @@ -22,6 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("LightStageSetup"); task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); + task.addJob("BloomStageSetup"); task.addJob("TransitionStageSetup"); task.addJob("HighlightStageSetup"); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 3299b0c41c..d85818a21a 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -21,11 +21,12 @@ #include "StencilMaskPass.h" #include "DeferredLightingEffect.h" - #include "render-utils/ShaderConstants.h" #include "StencilMaskPass.h" #include "DeferredLightingEffect.h" +#include "BloomStage.h" + namespace ru { using render_utils::slot::texture::Texture; using render_utils::slot::buffer::Buffer; @@ -63,7 +64,7 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu } void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { - // Grab light, background and haze stages and clear them + // Grab light, background, haze, and bloom stages and clear them auto lightStage = context->_scene->getStage(); assert(lightStage); lightStage->_currentFrame.clear(); @@ -76,6 +77,10 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) assert(hazeStage); hazeStage->_currentFrame.clear(); + auto bloomStage = context->_scene->getStage(); + assert(bloomStage); + bloomStage->_currentFrame.clear(); + // call render over the zones to grab their components in the correct order first... render::renderItems(context, inputs); @@ -84,6 +89,7 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight()); backgroundStage->_currentFrame.pushBackground(0); hazeStage->_currentFrame.pushHaze(0); + bloomStage->_currentFrame.pushBloom(0); } const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 9614f8b8fe..744150253d 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -678,6 +678,52 @@ +
+ + Bloom + +
+ Inherit + Off + On +
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d2cea2d394..43ea6bf22f 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -839,7 +839,7 @@ function loaded() { var elZoneHazeModeInherit = document.getElementById("property-zone-haze-mode-inherit"); var elZoneHazeModeDisabled = document.getElementById("property-zone-haze-mode-disabled"); var elZoneHazeModeEnabled = document.getElementById("property-zone-haze-mode-enabled"); - + var elZoneHazeRange = document.getElementById("property-zone-haze-range"); var elZoneHazeColor = document.getElementById("property-zone-haze-color"); var elZoneHazeColorRed = document.getElementById("property-zone-haze-color-red"); @@ -858,6 +858,15 @@ function loaded() { var elZoneHazeBackgroundBlend = document.getElementById("property-zone-haze-background-blend"); + // Bloom + var elZoneBloomModeInherit = document.getElementById("property-zone-bloom-mode-inherit"); + var elZoneBloomModeDisabled = document.getElementById("property-zone-bloom-mode-disabled"); + var elZoneBloomModeEnabled = document.getElementById("property-zone-bloom-mode-enabled"); + + var elZoneBloomIntensity = document.getElementById("property-zone-bloom-intensity"); + var elZoneBloomThreshold = document.getElementById("property-zone-bloom-threshold"); + var elZoneBloomSize = document.getElementById("property-zone-bloom-size"); + var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color"); var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red"); var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green"); @@ -914,19 +923,19 @@ function loaded() { deleteJSONMaterialEditor(); } } - + elTypeIcon.style.display = "none"; elType.innerHTML = "No selection"; elPropertiesList.className = ''; - + elID.value = ""; elName.value = ""; elLocked.checked = false; elVisible.checked = false; - + elParentID.value = ""; elParentJointIndex.value = ""; - + elColorRed.value = ""; elColorGreen.value = ""; elColorBlue.value = ""; @@ -935,15 +944,15 @@ function loaded() { elPositionX.value = ""; elPositionY.value = ""; elPositionZ.value = ""; - + elRotationX.value = ""; elRotationY.value = ""; elRotationZ.value = ""; - + elDimensionsX.value = ""; elDimensionsY.value = ""; elDimensionsZ.value = ""; - + elRegistrationX.value = ""; elRegistrationY.value = ""; elRegistrationZ.value = ""; @@ -965,14 +974,14 @@ function loaded() { elAccelerationX.value = ""; elAccelerationY.value = ""; elAccelerationZ.value = ""; - + elRestitution.value = ""; elFriction.value = ""; elDensity.value = ""; - + elCollisionless.checked = false; elDynamic.checked = false; - + elCollideStatic.checked = false; elCollideKinematic.checked = false; elCollideDynamic.checked = false; @@ -989,27 +998,27 @@ function loaded() { elCloneableGroup.style.display = "none"; elCloneableLimit.value = ""; elCloneableLifetime.value = ""; - - showElements(document.getElementsByClassName('can-cast-shadow-section'), true); + + showElements(document.getElementsByClassName('can-cast-shadow-section'), true); elCanCastShadow.checked = false; - + elCollisionSoundURL.value = ""; elLifetime.value = ""; elScriptURL.value = ""; elServerScripts.value = ""; elHyperlinkHref.value = ""; elDescription.value = ""; - + deleteJSONEditor(); elUserData.value = ""; showUserDataTextArea(); showSaveUserDataButton(); showNewJSONEditorButton(); - + // Shape Properties elShape.value = "Cube"; setDropdownText(elShape); - + // Light Properties elLightSpotLight.checked = false; elLightColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; @@ -1020,7 +1029,7 @@ function loaded() { elLightFalloffRadius.value = ""; elLightExponent.value = ""; elLightCutoff.value = ""; - + // Model Properties elModelURL.value = ""; elCompoundShapeURL.value = ""; @@ -1037,7 +1046,7 @@ function loaded() { elModelAnimationAllowTranslation.checked = false; elModelTextures.value = ""; elModelOriginalTextures.value = ""; - + // Zone Properties elZoneFlyingAllowed.checked = false; elZoneGhostingAllowed.checked = false; @@ -1067,6 +1076,9 @@ function loaded() { elZoneHazeAltitudeEffect.checked = false; elZoneHazeBaseRef.value = ""; elZoneHazeCeiling.value = ""; + elZoneBloomIntensity.value = ""; + elZoneBloomThreshold.value = ""; + elZoneBloomSize.value = ""; elZoneSkyboxColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; elZoneSkyboxColorRed.value = ""; elZoneSkyboxColorGreen.value = ""; @@ -1076,7 +1088,8 @@ function loaded() { showElements(document.getElementsByClassName('skybox-section'), true); showElements(document.getElementsByClassName('ambient-section'), true); showElements(document.getElementsByClassName('haze-section'), true); - + showElements(document.getElementsByClassName('bloom-section'), true); + // Text Properties elTextText.value = ""; elTextLineHeight.value = ""; @@ -1089,14 +1102,14 @@ function loaded() { elTextBackgroundColorRed.value = ""; elTextBackgroundColorGreen.value = ""; elTextBackgroundColorBlue.value = ""; - + // Image Properties elImageURL.value = ""; - + // Web Properties elWebSourceURL.value = ""; elWebDPI.value = ""; - + // Material Properties elMaterialURL.value = ""; elParentMaterialNameNumber.value = ""; @@ -1107,13 +1120,13 @@ function loaded() { elMaterialMappingScaleX.value = ""; elMaterialMappingScaleY.value = ""; elMaterialMappingRot.value = ""; - + deleteJSONMaterialEditor(); elMaterialData.value = ""; showMaterialDataTextArea(); showSaveMaterialDataButton(); showNewJSONMaterialEditorButton(); - + disableProperties(); } else if (data.selections.length > 1) { deleteJSONEditor(); @@ -1250,7 +1263,7 @@ function loaded() { elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = properties.cloneLimit; elCloneableLifetime.value = properties.cloneLifetime; - + var grabbablesSet = false; var parsedUserData = {}; try { @@ -1476,6 +1489,14 @@ function loaded() { elZoneHazeBaseRef.value = properties.haze.hazeBaseRef.toFixed(0); elZoneHazeCeiling.value = properties.haze.hazeCeiling.toFixed(0); + elZoneBloomModeInherit.checked = (properties.bloomMode === 'inherit'); + elZoneBloomModeDisabled.checked = (properties.bloomMode === 'disabled'); + elZoneBloomModeEnabled.checked = (properties.bloomMode === 'enabled'); + + elZoneBloomIntensity.value = properties.bloom.bloomIntensity.toFixed(2); + elZoneBloomThreshold.value = properties.bloom.bloomThreshold.toFixed(2); + elZoneBloomSize.value = properties.bloom.bloomSize.toFixed(2); + elShapeType.value = properties.shapeType; elCompoundShapeURL.value = properties.compoundShapeURL; @@ -1502,6 +1523,9 @@ function loaded() { showElements(document.getElementsByClassName('haze-section'), elZoneHazeModeEnabled.checked); + + showElements(document.getElementsByClassName('bloom-section'), + elZoneBloomModeEnabled.checked); } else if (properties.type === "PolyVox") { elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); @@ -2067,6 +2091,18 @@ function loaded() { elZoneHazeBackgroundBlend.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeBackgroundBlend')); + // Bloom + var bloomModeChanged = createZoneComponentModeChangedFunction('bloomMode', + elZoneBloomModeInherit, elZoneBloomModeDisabled, elZoneBloomModeEnabled); + + elZoneBloomModeInherit.addEventListener('change', bloomModeChanged); + elZoneBloomModeDisabled.addEventListener('change', bloomModeChanged); + elZoneBloomModeEnabled.addEventListener('change', bloomModeChanged); + + elZoneBloomIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomIntensity')); + elZoneBloomThreshold.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomThreshold')); + elZoneBloomSize.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomSize')); + var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox', 'color', elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction); From fb75b42059a6fc318f23579f9b9aebfaf8265459 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 7 Aug 2018 18:18:58 -0700 Subject: [PATCH 3/3] working on enabling bloom --- .../src/RenderableZoneEntityItem.cpp | 50 ++++++ .../src/RenderableZoneEntityItem.h | 31 ++-- libraries/entities/src/BloomPropertyGroup.cpp | 159 +++++++++++++++++ libraries/entities/src/BloomPropertyGroup.h | 94 ++++++++++ .../entities/src/EntityItemProperties.cpp | 51 +++++- libraries/entities/src/EntityItemProperties.h | 4 + libraries/entities/src/EntityPropertyFlags.h | 5 + libraries/entities/src/ZoneEntityItem.cpp | 165 ++++++++++-------- libraries/entities/src/ZoneEntityItem.h | 14 +- libraries/graphics/src/graphics/Bloom.cpp | 18 ++ libraries/graphics/src/graphics/Bloom.h | 44 +++++ .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/render-utils/src/BloomEffect.cpp | 93 +++++----- libraries/render-utils/src/BloomEffect.h | 49 +----- libraries/render-utils/src/BloomStage.cpp | 80 +++++++++ libraries/render-utils/src/BloomStage.h | 122 +++++++++++++ libraries/render-utils/src/HazeStage.h | 1 - .../render-utils/src/RenderDeferredTask.cpp | 9 +- .../render-utils/src/UpdateSceneTask.cpp | 2 + libraries/render-utils/src/ZoneRenderer.cpp | 10 +- scripts/system/html/entityProperties.html | 46 +++++ scripts/system/html/js/entityProperties.js | 88 +++++++--- 23 files changed, 919 insertions(+), 221 deletions(-) create mode 100644 libraries/entities/src/BloomPropertyGroup.cpp create mode 100644 libraries/entities/src/BloomPropertyGroup.h create mode 100644 libraries/graphics/src/graphics/Bloom.cpp create mode 100644 libraries/graphics/src/graphics/Bloom.h create mode 100644 libraries/render-utils/src/BloomStage.cpp create mode 100644 libraries/render-utils/src/BloomStage.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index c5035431f6..928d5ca6a3 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -64,6 +64,13 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity _hazeIndex = INVALID_INDEX; } } + + if (_bloomStage) { + if (!BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomStage->removeBloom(_bloomIndex); + _bloomIndex = INVALID_INDEX; + } + } } void ZoneEntityRenderer::doRender(RenderArgs* args) { @@ -112,6 +119,11 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { assert(_hazeStage); } + if (!_bloomStage) { + _bloomStage = args->_scene->getStage(); + assert(_bloomStage); + } + { // Sun // Need an update ? if (_needSunUpdate) { @@ -161,6 +173,15 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { } } + { + if (_needBloomUpdate) { + if (BloomStage::isIndexInvalid(_bloomIndex)) { + _bloomIndex = _bloomStage->addBloom(_bloom); + } + _needBloomUpdate = false; + } + } + if (_visible) { // Finally, push the lights visible in the frame // @@ -190,6 +211,12 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { if (_hazeMode != COMPONENT_MODE_INHERIT) { _hazeStage->_currentFrame.pushHaze(_hazeIndex); } + + if (_bloomMode == COMPONENT_MODE_DISABLED) { + _bloomStage->_currentFrame.pushBloom(INVALID_INDEX); + } else if (_ambientLightMode == COMPONENT_MODE_ENABLED) { + _bloomStage->_currentFrame.pushBloom(_bloomIndex); + } } } @@ -211,6 +238,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen bool ambientLightChanged = entity->ambientLightPropertiesChanged(); bool skyboxChanged = entity->skyboxPropertiesChanged(); bool hazeChanged = entity->hazePropertiesChanged(); + bool bloomChanged = entity->bloomPropertiesChanged(); entity->resetRenderingPropertiesChanged(); _lastPosition = entity->getWorldPosition(); @@ -221,6 +249,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen _ambientLightProperties = entity->getAmbientLightProperties(); _skyboxProperties = entity->getSkyboxProperties(); _hazeProperties = entity->getHazeProperties(); + _bloomProperties = entity->getBloomProperties(); #if 0 if (_lastShapeURL != _typedEntity->getCompoundShapeURL()) { @@ -258,6 +287,10 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen if (hazeChanged) { updateHazeFromEntity(entity); } + + if (bloomChanged) { + updateBloomFromEntity(entity); + } } void ZoneEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { @@ -276,6 +309,7 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (entity->keyLightPropertiesChanged() || entity->ambientLightPropertiesChanged() || entity->hazePropertiesChanged() || + entity->bloomPropertiesChanged() || entity->skyboxPropertiesChanged()) { return true; @@ -388,6 +422,18 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity) haze->setTransform(entity->getTransform().getMatrix()); } +void ZoneEntityRenderer::updateBloomFromEntity(const TypedEntityPointer& entity) { + setBloomMode((ComponentMode)entity->getBloomMode()); + + const auto& bloom = editBloom(); + + const uint32_t bloomMode = entity->getBloomMode(); + bloom->setBloomActive(bloomMode == COMPONENT_MODE_ENABLED); + bloom->setBloomIntensity(_bloomProperties.getBloomIntensity()); + bloom->setBloomThreshold(_bloomProperties.getBloomThreshold()); + bloom->setBloomSize(_bloomProperties.getBloomSize()); +} + void ZoneEntityRenderer::updateKeyBackgroundFromEntity(const TypedEntityPointer& entity) { setSkyboxMode((ComponentMode)entity->getSkyboxMode()); @@ -510,6 +556,10 @@ void ZoneEntityRenderer::setSkyboxMode(ComponentMode mode) { _skyboxMode = mode; } +void ZoneEntityRenderer::setBloomMode(ComponentMode mode) { + _bloomMode = mode; +} + void ZoneEntityRenderer::setSkyboxColor(const glm::vec3& color) { editSkybox()->setColor(color); } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index c48679e5d4..3e2690e1bd 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -1,7 +1,6 @@ // // RenderableZoneEntityItem.h // -// // Created by Clement on 4/22/15. // Copyright 2015 High Fidelity, Inc. // @@ -15,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include "RenderableEntityItem.h" #include @@ -50,6 +51,7 @@ private: void updateAmbientLightFromEntity(const TypedEntityPointer& entity); void updateHazeFromEntity(const TypedEntityPointer& entity); void updateKeyBackgroundFromEntity(const TypedEntityPointer& entity); + void updateBloomFromEntity(const TypedEntityPointer& entity); void updateAmbientMap(); void updateSkyboxMap(); void setAmbientURL(const QString& ambientUrl); @@ -59,6 +61,7 @@ private: void setKeyLightMode(ComponentMode mode); void setAmbientLightMode(ComponentMode mode); void setSkyboxMode(ComponentMode mode); + void setBloomMode(ComponentMode mode); void setSkyboxColor(const glm::vec3& color); void setProceduralUserData(const QString& userData); @@ -68,6 +71,7 @@ private: graphics::SunSkyStagePointer editBackground() { _needBackgroundUpdate = true; return _background; } graphics::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); } graphics::HazePointer editHaze() { _needHazeUpdate = true; return _haze; } + graphics::BloomPointer editBloom() { _needBloomUpdate = true; return _bloom; } glm::vec3 _lastPosition; glm::vec3 _lastDimensions; @@ -82,36 +86,43 @@ private: #endif LightStagePointer _stage; - const graphics::LightPointer _sunLight{ std::make_shared() }; - const graphics::LightPointer _ambientLight{ std::make_shared() }; - const graphics::SunSkyStagePointer _background{ std::make_shared() }; - const graphics::HazePointer _haze{ std::make_shared() }; + const graphics::LightPointer _sunLight { std::make_shared() }; + const graphics::LightPointer _ambientLight { std::make_shared() }; + const graphics::SunSkyStagePointer _background { std::make_shared() }; + const graphics::HazePointer _haze { std::make_shared() }; + const graphics::BloomPointer _bloom { std::make_shared() }; 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 }; - indexed_container::Index _sunIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _shadowIndex{ LightStage::INVALID_INDEX }; - indexed_container::Index _ambientIndex{ LightStage::INVALID_INDEX }; + indexed_container::Index _sunIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _shadowIndex { LightStage::INVALID_INDEX }; + indexed_container::Index _ambientIndex { LightStage::INVALID_INDEX }; BackgroundStagePointer _backgroundStage; - BackgroundStage::Index _backgroundIndex{ BackgroundStage::INVALID_INDEX }; + BackgroundStage::Index _backgroundIndex { BackgroundStage::INVALID_INDEX }; HazeStagePointer _hazeStage; - HazeStage::Index _hazeIndex{ HazeStage::INVALID_INDEX }; + HazeStage::Index _hazeIndex { HazeStage::INVALID_INDEX }; + + BloomStagePointer _bloomStage; + BloomStage::Index _bloomIndex { BloomStage::INVALID_INDEX }; bool _needUpdate{ true }; bool _needSunUpdate{ true }; bool _needAmbientUpdate{ true }; bool _needBackgroundUpdate{ true }; bool _needHazeUpdate{ true }; + bool _needBloomUpdate { true }; KeyLightPropertyGroup _keyLightProperties; AmbientLightPropertyGroup _ambientLightProperties; HazePropertyGroup _hazeProperties; SkyboxPropertyGroup _skyboxProperties; + BloomPropertyGroup _bloomProperties; // More attributes used for rendering: QString _ambientTextureURL; diff --git a/libraries/entities/src/BloomPropertyGroup.cpp b/libraries/entities/src/BloomPropertyGroup.cpp new file mode 100644 index 0000000000..2c4d46ab35 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.cpp @@ -0,0 +1,159 @@ +// +// BloomPropertyGroup.cpp +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "BloomPropertyGroup.h" + +#include + +#include "EntityItemProperties.h" +#include "EntityItemPropertiesMacros.h" + +void BloomPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); +} + +void BloomPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomIntensity, float, setBloomIntensity); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomThreshold, float, setBloomThreshold); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(bloom, bloomSize, float, setBloomSize); +} + +void BloomPropertyGroup::merge(const BloomPropertyGroup& other) { + COPY_PROPERTY_IF_CHANGED(bloomIntensity); + COPY_PROPERTY_IF_CHANGED(bloomThreshold); + COPY_PROPERTY_IF_CHANGED(bloomSize); +} + +void BloomPropertyGroup::debugDump() const { + qCDebug(entities) << " BloomPropertyGroup: ---------------------------------------------"; + qCDebug(entities) << " _bloomIntensity:" << _bloomIntensity; + qCDebug(entities) << " _bloomThreshold:" << _bloomThreshold; + qCDebug(entities) << " _bloomSize:" << _bloomSize; +} + +void BloomPropertyGroup::listChangedProperties(QList& out) { + if (bloomIntensityChanged()) { + out << "bloom-bloomIntensity"; + } + if (bloomThresholdChanged()) { + out << "bloom-bloomThreshold"; + } + if (bloomSizeChanged()) { + out << "bloom-bloomSize"; + } +} + +bool BloomPropertyGroup::appendToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); + + return true; +} + +bool BloomPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) { + int bytesRead = 0; + bool overwriteLocalData = true; + bool somethingChanged = false; + + READ_ENTITY_PROPERTY(PROP_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_INTENSITY, BloomIntensity); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_THRESHOLD, BloomThreshold); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_BLOOM_SIZE, BloomSize); + + processedBytes += bytesRead; + + Q_UNUSED(somethingChanged); + + return true; +} + +void BloomPropertyGroup::markAllChanged() { + _bloomIntensityChanged = true; + _bloomThresholdChanged = true; + _bloomSizeChanged = true; +} + +EntityPropertyFlags BloomPropertyGroup::getChangedProperties() const { + EntityPropertyFlags changedProperties; + + CHECK_PROPERTY_CHANGE(PROP_BLOOM_INTENSITY, bloomIntensity); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_THRESHOLD, bloomThreshold); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_SIZE, bloomSize); + + return changedProperties; +} + +void BloomPropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomIntensity, getBloomIntensity); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomThreshold, getBloomThreshold); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Bloom, BloomSize, getBloomSize); +} + +bool BloomPropertyGroup::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomIntensity, bloomIntensity, setBloomIntensity); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomThreshold, bloomThreshold, setBloomThreshold); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Bloom, BloomSize, bloomSize, setBloomSize); + + return somethingChanged; +} + +EntityPropertyFlags BloomPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties; + + requestedProperties += PROP_BLOOM_INTENSITY; + requestedProperties += PROP_BLOOM_THRESHOLD; + requestedProperties += PROP_BLOOM_SIZE; + + return requestedProperties; +} + +void BloomPropertyGroup::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_BLOOM_INTENSITY, getBloomIntensity()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, getBloomThreshold()); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_SIZE, getBloomSize()); +} + +int BloomPropertyGroup::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_BLOOM_INTENSITY, float, setBloomIntensity); + READ_ENTITY_PROPERTY(PROP_BLOOM_THRESHOLD, float, setBloomThreshold); + READ_ENTITY_PROPERTY(PROP_BLOOM_SIZE, float, setBloomSize); + + return bytesRead; +} diff --git a/libraries/entities/src/BloomPropertyGroup.h b/libraries/entities/src/BloomPropertyGroup.h new file mode 100644 index 0000000000..a1f9b6d748 --- /dev/null +++ b/libraries/entities/src/BloomPropertyGroup.h @@ -0,0 +1,94 @@ +// +// BloomPropertyGroup.h +// libraries/entities/src +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_BloomPropertyGroup_h +#define hifi_BloomPropertyGroup_h + +#include +#include + +#include + +#include "PropertyGroup.h" +#include "EntityItemPropertiesMacros.h" + +class EntityItemProperties; +class EncodeBitstreamParams; +class OctreePacketData; +class EntityTreeElementExtraEncodeData; +class ReadBitstreamToTreeParams; + +static const float INITIAL_BLOOM_INTENSITY { 0.25f }; +static const float INITIAL_BLOOM_THRESHOLD { 0.7f }; +static const float INITIAL_BLOOM_SIZE { 0.9f }; + +/**jsdoc + * Bloom is defined by the following properties. + * @typedef {object} Entities.Bloom + * + * @property {number} bloomIntensity=0.25 - The intensity of the bloom effect. + * @property {number} bloomThreshold=0.7 - The threshold for the bloom effect. + * @property {number} bloomSize=0.9 - The size of the bloom effect. + */ +class BloomPropertyGroup : public PropertyGroup { +public: + // EntityItemProperty related helpers + virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, + QScriptEngine* engine, bool skipDefaults, + EntityItemProperties& defaultEntityProperties) const override; + virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) override; + + void merge(const BloomPropertyGroup& other); + + virtual void debugDump() const override; + virtual void listChangedProperties(QList& 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(PROP_BLOOM_INTENSITY, BloomIntensity, bloomIntensity, float, INITIAL_BLOOM_INTENSITY); + DEFINE_PROPERTY(PROP_BLOOM_THRESHOLD, BloomThreshold, bloomThreshold, float, INITIAL_BLOOM_THRESHOLD); + DEFINE_PROPERTY(PROP_BLOOM_SIZE, BloomSize, bloomSize, float, INITIAL_BLOOM_SIZE); + +}; + +#endif // hifi_BloomPropertyGroup_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1f9bf2eb18..68d0e6aed4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -37,6 +37,7 @@ AnimationPropertyGroup EntityItemProperties::_staticAnimation; SkyboxPropertyGroup EntityItemProperties::_staticSkybox; HazePropertyGroup EntityItemProperties::_staticHaze; +BloomPropertyGroup EntityItemProperties::_staticBloom; KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; AmbientLightPropertyGroup EntityItemProperties::_staticAmbientLight; @@ -84,6 +85,7 @@ void EntityItemProperties::debugDump() const { getHaze().debugDump(); getKeyLight().debugDump(); getAmbientLight().debugDump(); + getBloom().debugDump(); qCDebug(entities) << " changed properties..."; EntityPropertyFlags props = getChangedProperties(); @@ -211,6 +213,10 @@ QString EntityItemProperties::getHazeModeAsString() const { return getComponentModeAsString(_hazeMode); } +QString EntityItemProperties::getBloomModeAsString() const { + return getComponentModeAsString(_bloomMode); +} + QString EntityItemProperties::getComponentModeString(uint32_t mode) { // return "inherit" if mode is not valid if (mode < COMPONENT_MODE_ITEM_COUNT) { @@ -235,6 +241,15 @@ void EntityItemProperties::setHazeModeFromString(const QString& hazeMode) { } } +void EntityItemProperties::setBloomModeFromString(const QString& bloomMode) { + auto result = findComponent(bloomMode); + + if (result != COMPONENT_MODES.end()) { + _bloomMode = result->first; + _bloomModeChanged = true; + } +} + QString EntityItemProperties::getKeyLightModeAsString() const { return getComponentModeAsString(_keyLightMode); } @@ -394,6 +409,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_KEY_LIGHT_MODE, keyLightMode); CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); + CHECK_PROPERTY_CHANGE(PROP_BLOOM_MODE, bloomMode); CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); @@ -454,6 +470,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { changedProperties += _ambientLight.getChangedProperties(); changedProperties += _skybox.getChangedProperties(); changedProperties += _haze.getChangedProperties(); + changedProperties += _bloom.getChangedProperties(); return changedProperties; } @@ -1164,6 +1181,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * "enabled": The haze properties of this zone are enabled, overriding the haze from any enclosing zone. * @property {Entities.Haze} haze - The haze properties of the zone. * + * @property {string} bloomMode="inherit" - Configures the bloom in the zone. Possible values:
+ * "inherit": The bloom from any enclosing zone continues into this zone.
+ * "disabled": The bloom from any enclosing zone and the bloom of this zone are disabled in this zone.
+ * "enabled": The bloom properties of this zone are enabled, overriding the bloom from any enclosing zone. + * @property {Entities.Bloom} bloom - The bloom properties of the zone. + * * @property {boolean} flyingAllowed=true - If true then visitors can fly in the zone; otherwise they cannot. * @property {boolean} ghostingAllowed=true - If true then visitors with avatar collisions turned off will not * collide with content in the zone; otherwise visitors will always collide with content in the zone. @@ -1382,6 +1405,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString()); _haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString()); + _bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); @@ -1630,6 +1656,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(keyLightMode, KeyLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(bloomMode, BloomMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, vec3, setVoxelVolumeSize); @@ -1662,6 +1689,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool _ambientLight.copyFromScriptValue(object, _defaultSettings); _skybox.copyFromScriptValue(object, _defaultSettings); _haze.copyFromScriptValue(object, _defaultSettings); + _bloom.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(xTextureURL, QString, setXTextureURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(yTextureURL, QString, setYTextureURL); @@ -1803,6 +1831,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(keyLightMode); COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); + COPY_PROPERTY_IF_CHANGED(bloomMode); COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); @@ -1825,6 +1854,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { _ambientLight.merge(other._ambientLight); _skybox.merge(other._skybox); _haze.merge(other._haze); + _bloom.merge(other._bloom); COPY_PROPERTY_IF_CHANGED(xTextureURL); COPY_PROPERTY_IF_CHANGED(yTextureURL); @@ -2096,6 +2126,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_RANGE, Haze, haze, HazeKeyLightRange, hazeKeyLightRange); ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_KEYLIGHT_ALTITUDE, Haze, haze, HazeKeyLightAltitude, hazeKeyLightAltitude); + ADD_PROPERTY_TO_MAP(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_INTENSITY, Bloom, bloom, BloomIntensity, bloomIntensity); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_THRESHOLD, Bloom, bloom, BloomThreshold, bloomThreshold); + ADD_GROUP_PROPERTY_TO_MAP(PROP_BLOOM_SIZE, Bloom, bloom, BloomSize, bloomSize); + ADD_PROPERTY_TO_MAP(PROP_KEY_LIGHT_MODE, KeyLightMode, keyLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t); ADD_PROPERTY_TO_MAP(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t); @@ -2357,6 +2392,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticHaze.setProperties(properties); _staticHaze.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BLOOM_MODE, (uint32_t)properties.getBloomMode()); + _staticBloom.setProperties(properties); + _staticBloom.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, (uint32_t)properties.getKeyLightMode()); APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, (uint32_t)properties.getAmbientLightMode()); APPEND_ENTITY_PROPERTY(PROP_SKYBOX_MODE, (uint32_t)properties.getSkyboxMode()); @@ -2731,6 +2770,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HAZE_MODE, uint32_t, setHazeMode); properties.getHaze().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BLOOM_MODE, uint32_t, setBloomMode); + properties.getBloom().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); @@ -3044,10 +3086,12 @@ void EntityItemProperties::markAllChanged() { _skyboxModeChanged = true; _ambientLightModeChanged = true; _hazeModeChanged = true; + _bloomModeChanged = true; _animation.markAllChanged(); _skybox.markAllChanged(); _haze.markAllChanged(); + _bloom.markAllChanged(); _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; @@ -3442,15 +3486,15 @@ QList EntityItemProperties::listChangedProperties() { if (hazeModeChanged()) { out += "hazeMode"; } - + if (bloomModeChanged()) { + out += "bloomMode"; + } if (keyLightModeChanged()) { out += "keyLightMode"; } - if (ambientLightModeChanged()) { out += "ambientLightMode"; } - if (skyboxModeChanged()) { out += "skyboxMode"; } @@ -3581,6 +3625,7 @@ QList EntityItemProperties::listChangedProperties() { getAmbientLight().listChangedProperties(out); getSkybox().listChangedProperties(out); getHaze().listChangedProperties(out); + getBloom().listChangedProperties(out); return out; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 04e54c54a5..50305345de 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -42,6 +42,7 @@ #include "SimulationOwner.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include "TextEntityItem.h" #include "ZoneEntityItem.h" @@ -195,9 +196,11 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); + DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT); DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup); DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); + DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); @@ -533,6 +536,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, KeyLightMode, keyLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, AmbientLightMode, ambientLightMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, SkyboxMode, skyboxMode, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, BloomMode, bloomMode, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Cloneable, cloneable, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, CloneLifetime, cloneLifetime, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 156c5d9dd4..3932730661 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -257,6 +257,11 @@ enum EntityPropertyList { PROP_SPIN_SPREAD, PROP_PARTICLE_ROTATE_WITH_ENTITY, + PROP_BLOOM_MODE, + PROP_BLOOM_INTENSITY, + PROP_BLOOM_THRESHOLD, + PROP_BLOOM_SIZE, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index f2550e5d3c..a7dfa1a41e 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -47,33 +47,27 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - // Contains a QString property, must be synchronized + // Contain QString properties, must be synchronized withReadLock([&] { _keyLightProperties.getProperties(properties); - }); - - withReadLock([&] { _ambientLightProperties.getProperties(properties); + _skyboxProperties.getProperties(properties); }); + _hazeProperties.getProperties(properties); + _bloomProperties.getProperties(properties); COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); - // Contains a QString property, must be synchronized - withReadLock([&] { - _skyboxProperties.getProperties(properties); - }); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed); COPY_ENTITY_PROPERTY_TO_PROPERTIES(filterURL, getFilterURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(hazeMode, getHazeMode); - _hazeProperties.getProperties(properties); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(keyLightMode, getKeyLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ambientLightMode, getAmbientLightMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(skyboxMode, getSkyboxMode); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(bloomMode, getBloomMode); return properties; } @@ -102,32 +96,27 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie // Contains a QString property, must be synchronized withWriteLock([&] { _keyLightPropertiesChanged = _keyLightProperties.setProperties(properties); - }); - withWriteLock([&] { _ambientLightPropertiesChanged = _ambientLightProperties.setProperties(properties); + _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); }); + _hazePropertiesChanged = _hazeProperties.setProperties(properties); + _bloomPropertiesChanged = _bloomProperties.setProperties(properties); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); - // Contains a QString property, must be synchronized - withWriteLock([&] { - _skyboxPropertiesChanged = _skyboxProperties.setProperties(properties); - }); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed); SET_ENTITY_PROPERTY_FROM_PROPERTIES(filterURL, setFilterURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(hazeMode, setHazeMode); - _hazePropertiesChanged = _hazeProperties.setProperties(properties); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(keyLightMode, setKeyLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ambientLightMode, setAmbientLightMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(skyboxMode, setSkyboxMode); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(bloomMode, setBloomMode); somethingChanged = somethingChanged || _keyLightPropertiesChanged || _ambientLightPropertiesChanged || - _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged; + _stagePropertiesChanged || _skyboxPropertiesChanged || _hazePropertiesChanged || _bloomPropertiesChanged; return somethingChanged; } @@ -139,54 +128,67 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; - int bytesFromKeylight; - withWriteLock([&] { - bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); - }); + { + int bytesFromKeylight; + withWriteLock([&] { + bytesFromKeylight = _keyLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _keyLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _keyLightPropertiesChanged; + bytesRead += bytesFromKeylight; + dataAt += bytesFromKeylight; + } - somethingChanged = somethingChanged || _keyLightPropertiesChanged; - bytesRead += bytesFromKeylight; - dataAt += bytesFromKeylight; + { + int bytesFromAmbientlight; + withWriteLock([&] { + bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); + }); + somethingChanged = somethingChanged || _ambientLightPropertiesChanged; + bytesRead += bytesFromAmbientlight; + dataAt += bytesFromAmbientlight; + } - int bytesFromAmbientlight; - withWriteLock([&] { - bytesFromAmbientlight = _ambientLightProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _ambientLightPropertiesChanged); - }); + { + int bytesFromSkybox; + withWriteLock([&] { + bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); + }); + somethingChanged = somethingChanged || _skyboxPropertiesChanged; + bytesRead += bytesFromSkybox; + dataAt += bytesFromSkybox; + } - somethingChanged = somethingChanged || _ambientLightPropertiesChanged; - bytesRead += bytesFromAmbientlight; - dataAt += bytesFromAmbientlight; + { + int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _hazePropertiesChanged); + somethingChanged = somethingChanged || _hazePropertiesChanged; + bytesRead += bytesFromHaze; + dataAt += bytesFromHaze; + } + + { + int bytesFromBloom = _bloomProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, _bloomPropertiesChanged); + somethingChanged = somethingChanged || _bloomPropertiesChanged; + bytesRead += bytesFromBloom; + dataAt += bytesFromBloom; + } READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); - int bytesFromSkybox; - withWriteLock([&] { - bytesFromSkybox = _skyboxProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _skyboxPropertiesChanged); - }); - somethingChanged = somethingChanged || _skyboxPropertiesChanged; - bytesRead += bytesFromSkybox; - dataAt += bytesFromSkybox; - READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed); READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed); READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL); READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint32_t, setHazeMode); - - int bytesFromHaze = _hazeProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, - propertyFlags, overwriteLocalData, _hazePropertiesChanged); - - somethingChanged = somethingChanged || _hazePropertiesChanged; - bytesRead += bytesFromHaze; - dataAt += bytesFromHaze; - READ_ENTITY_PROPERTY(PROP_KEY_LIGHT_MODE, uint32_t, setKeyLightMode); READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_MODE, uint32_t, setAmbientLightMode); READ_ENTITY_PROPERTY(PROP_SKYBOX_MODE, uint32_t, setSkyboxMode); + READ_ENTITY_PROPERTY(PROP_BLOOM_MODE, uint32_t, setBloomMode); return bytesRead; } @@ -196,29 +198,24 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p withReadLock([&] { requestedProperties += _keyLightProperties.getEntityProperties(params); - }); - - withReadLock([&] { requestedProperties += _ambientLightProperties.getEntityProperties(params); + requestedProperties += _skyboxProperties.getEntityProperties(params); }); + requestedProperties += _hazeProperties.getEntityProperties(params); + requestedProperties += _bloomProperties.getEntityProperties(params); requestedProperties += PROP_SHAPE_TYPE; requestedProperties += PROP_COMPOUND_SHAPE_URL; - withReadLock([&] { - requestedProperties += _skyboxProperties.getEntityProperties(params); - }); - requestedProperties += PROP_FLYING_ALLOWED; requestedProperties += PROP_GHOSTING_ALLOWED; requestedProperties += PROP_FILTER_URL; requestedProperties += PROP_HAZE_MODE; - requestedProperties += _hazeProperties.getEntityProperties(params); - requestedProperties += PROP_KEY_LIGHT_MODE; requestedProperties += PROP_AMBIENT_LIGHT_MODE; requestedProperties += PROP_SKYBOX_MODE; + requestedProperties += PROP_BLOOM_MODE; return requestedProperties; } @@ -235,44 +232,46 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); - _ambientLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + _skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + _bloomProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL()); - _skyboxProperties.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_HAZE_MODE, (uint32_t)getHazeMode()); - _hazeProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties, - propertyFlags, propertiesDidntFit, propertyCount, appendState); - 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_BLOOM_MODE, (uint32_t)getBloomMode()); } 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::getComponentModeString(_hazeMode); - qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); - qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); - qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getComponentModeString(_hazeMode); + qCDebug(entities) << " _keyLightMode:" << EntityItemProperties::getComponentModeString(_keyLightMode); + qCDebug(entities) << " _ambientLightMode:" << EntityItemProperties::getComponentModeString(_ambientLightMode); + qCDebug(entities) << " _skyboxMode:" << EntityItemProperties::getComponentModeString(_skyboxMode); + qCDebug(entities) << " _bloomMode:" << EntityItemProperties::getComponentModeString(_bloomMode); _keyLightProperties.debugDump(); _ambientLightProperties.debugDump(); _skyboxProperties.debugDump(); _hazeProperties.debugDump(); + _bloomProperties.debugDump(); } ShapeType ZoneEntityItem::getShapeType() const { @@ -344,6 +343,7 @@ void ZoneEntityItem::resetRenderingPropertiesChanged() { _ambientLightPropertiesChanged = false; _skyboxPropertiesChanged = false; _hazePropertiesChanged = false; + _bloomPropertiesChanged = false; _stagePropertiesChanged = false; }); } @@ -359,6 +359,17 @@ 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; diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 0aaa32a57a..e2ebf16f11 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -18,6 +18,7 @@ #include "EntityTree.h" #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" +#include "BloomPropertyGroup.h" #include class ZoneEntityItem : public EntityItem { @@ -79,9 +80,13 @@ public: void setSkyboxMode(uint32_t value); uint32_t getSkyboxMode() const; + void setBloomMode(const uint32_t value); + uint32_t getBloomMode() const; + SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock([&] { return _skyboxProperties; }); } const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; } + const BloomPropertyGroup& getBloomProperties() const { return _bloomProperties; } bool getFlyingAllowed() const { return _flyingAllowed; } void setFlyingAllowed(bool value) { _flyingAllowed = value; } @@ -93,10 +98,8 @@ public: bool keyLightPropertiesChanged() const { return _keyLightPropertiesChanged; } bool ambientLightPropertiesChanged() const { return _ambientLightPropertiesChanged; } bool skyboxPropertiesChanged() const { return _skyboxPropertiesChanged; } - - bool hazePropertiesChanged() const { - return _hazePropertiesChanged; - } + bool hazePropertiesChanged() const { return _hazePropertiesChanged; } + bool bloomPropertiesChanged() const { return _bloomPropertiesChanged; } bool stagePropertiesChanged() const { return _stagePropertiesChanged; } @@ -133,9 +136,11 @@ protected: uint32_t _ambientLightMode { COMPONENT_MODE_INHERIT }; uint32_t _hazeMode { COMPONENT_MODE_INHERIT }; + uint32_t _bloomMode { COMPONENT_MODE_INHERIT }; SkyboxPropertyGroup _skyboxProperties; HazePropertyGroup _hazeProperties; + BloomPropertyGroup _bloomProperties; bool _flyingAllowed { DEFAULT_FLYING_ALLOWED }; bool _ghostingAllowed { DEFAULT_GHOSTING_ALLOWED }; @@ -146,6 +151,7 @@ protected: bool _ambientLightPropertiesChanged { false }; bool _skyboxPropertiesChanged { false }; bool _hazePropertiesChanged{ false }; + bool _bloomPropertiesChanged { false }; bool _stagePropertiesChanged { false }; static bool _drawZoneBoundaries; diff --git a/libraries/graphics/src/graphics/Bloom.cpp b/libraries/graphics/src/graphics/Bloom.cpp new file mode 100644 index 0000000000..f8dcda3292 --- /dev/null +++ b/libraries/graphics/src/graphics/Bloom.cpp @@ -0,0 +1,18 @@ +// +// Bloom.cpp +// libraries/graphics/src/graphics +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Bloom.h" + +using namespace graphics; + +const float Bloom::INITIAL_BLOOM_INTENSITY { 0.25f }; +const float Bloom::INITIAL_BLOOM_THRESHOLD { 0.7f }; +const float Bloom::INITIAL_BLOOM_SIZE { 0.9f }; \ No newline at end of file diff --git a/libraries/graphics/src/graphics/Bloom.h b/libraries/graphics/src/graphics/Bloom.h new file mode 100644 index 0000000000..02362ce25d --- /dev/null +++ b/libraries/graphics/src/graphics/Bloom.h @@ -0,0 +1,44 @@ +// +// Bloom.h +// libraries/graphics/src/graphics +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Bloom_h +#define hifi_model_Bloom_h + +#include + +namespace graphics { + class Bloom { + public: + // Initial values + static const float INITIAL_BLOOM_INTENSITY; + static const float INITIAL_BLOOM_THRESHOLD; + static const float INITIAL_BLOOM_SIZE; + + Bloom() {} + + void setBloomIntensity(const float bloomIntensity) { _bloomIntensity = bloomIntensity; } + void setBloomThreshold(const float bloomThreshold) { _bloomThreshold = bloomThreshold; } + void setBloomSize(const float bloomSize) { _bloomSize = bloomSize; } + void setBloomActive(const bool isBloomActive) { _isBloomActive = isBloomActive; } + + float getBloomIntensity() { return _bloomIntensity; } + float getBloomThreshold() { return _bloomThreshold; } + float getBloomSize() { return _bloomSize; } + bool getBloomActive() { return _isBloomActive; } + + private: + bool _isBloomActive { false }; + float _bloomIntensity { INITIAL_BLOOM_INTENSITY }; + float _bloomThreshold {INITIAL_BLOOM_THRESHOLD }; + float _bloomSize { INITIAL_BLOOM_SIZE }; + }; + using BloomPointer = std::shared_ptr; +} +#endif // hifi_model_Bloom_h diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 82e9820509..ae165af5d1 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::ParticleSpin); + return static_cast(EntityVersion::BloomEffect); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 64c5bfe534..bfc92b9bde 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -240,7 +240,8 @@ enum class EntityVersion : PacketVersion { CollisionMask16Bytes, YieldSimulationOwnership, ParticleEntityFix, - ParticleSpin + ParticleSpin, + BloomEffect }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 2a9a9b3850..bd1f0fa9d2 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -25,11 +25,7 @@ BloomThreshold::BloomThreshold(unsigned int downsamplingFactor) { _parameters.edit()._sampleCount = downsamplingFactor; } -void BloomThreshold::configure(const Config& config) { - if (_parameters.get()._threshold != config.threshold) { - _parameters.edit()._threshold = config.threshold; - } -} +void BloomThreshold::configure(const Config& config) {} void BloomThreshold::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); @@ -39,6 +35,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons const auto frameTransform = inputs.get0(); const auto inputFrameBuffer = inputs.get1(); + const auto bloom = inputs.get2(); assert(inputFrameBuffer->hasColor()); @@ -68,6 +65,28 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; + if (!bloom || !bloom->getBloomActive()) { + outputs = _outputBuffer; + return; + } + + _parameters.edit()._threshold = bloom->getBloomThreshold(); + auto sigma = 0.5f + bloom->getBloomSize() * 3.5f; + + //{ + // std::string blurName { "BloomBlurN" }; + // auto task = static_cast(this); + + // for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { + // blurName.back() = '0' + i; + // auto blurJobIt = task->editJob(blurName); + // assert(blurJobIt != task->_jobs.end()); + // auto& gaussianBlur = blurJobIt->edit(); + // auto gaussianBlurParams = gaussianBlur.getParameters(); + // gaussianBlurParams->setFilterGaussianTaps(9, sigma); + // } + //} + gpu::doInBatch("BloomThreshold::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -90,16 +109,7 @@ BloomApply::BloomApply() { } -void BloomApply::configure(const Config& config) { - const auto newIntensity = config.intensity / 3.0f; - - if (_parameters.get()._intensities.x != newIntensity) { - auto& parameters = _parameters.edit(); - parameters._intensities.x = newIntensity; - parameters._intensities.y = newIntensity; - parameters._intensities.z = newIntensity; - } -} +void BloomApply::configure(const Config& config) {} void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); @@ -123,8 +133,19 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In const auto blur0FB = inputs.get1(); const auto blur1FB = inputs.get2(); const auto blur2FB = inputs.get3(); + const auto bloom = inputs.get4(); const glm::ivec4 viewport{ 0, 0, framebufferSize.x, framebufferSize.y }; + if (!bloom || !bloom->getBloomActive()) { + return; + } + + const auto newIntensity = bloom->getBloomIntensity() / 3.0f; + auto& parameters = _parameters.edit(); + parameters._intensities.x = newIntensity; + parameters._intensities.y = newIntensity; + parameters._intensities.z = newIntensity; + gpu::doInBatch("BloomApply::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -266,43 +287,9 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In }); } -void BloomConfig::setIntensity(float value) { - auto task = static_cast(_task); - auto blurJobIt = task->editJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - blurJobIt->getConfiguration()->setProperty("intensity", value); -} +BloomEffect::BloomEffect() {} -float BloomConfig::getIntensity() const { - auto task = static_cast(_task); - auto blurJobIt = task->getJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - return blurJobIt->getConfiguration()->property("intensity").toFloat(); -} - -void BloomConfig::setSize(float value) { - std::string blurName{ "BloomBlurN" }; - auto sigma = 0.5f+value*3.5f; - auto task = static_cast(_task); - - for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { - blurName.back() = '0' + i; - auto blurJobIt = task->editJob(blurName); - assert(blurJobIt != task->_jobs.end()); - auto& gaussianBlur = blurJobIt->edit(); - auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps(9, sigma); - } - auto blurJobIt = task->getJob("BloomApply"); - assert(blurJobIt != task->_jobs.end()); - blurJobIt->getConfiguration()->setProperty("sigma", sigma); -} - -Bloom::Bloom() { - -} - -void Bloom::configure(const Config& config) { +void BloomEffect::configure(const Config& config) { std::string blurName{ "BloomBlurN" }; for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { @@ -312,7 +299,7 @@ void Bloom::configure(const Config& config) { } } -void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { +void BloomEffect::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { // Start by computing threshold of color buffer input at quarter resolution const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs, 4U); @@ -325,7 +312,7 @@ void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying const auto& frameBuffer = input[1]; // Mix all blur levels at quarter resolution - const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying(); + const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2, input[2]).asVarying(); task.addJob("BloomApply", applyInput); // And then blend result in additive manner on top of final color buffer const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying(); diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 04cb4a9474..150a134dac 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -14,42 +14,21 @@ #include +#include "graphics/Bloom.h" + #include "DeferredFrameTransform.h" class BloomConfig : public render::Task::Config { Q_OBJECT - Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity NOTIFY dirty) - Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) - -public: - - BloomConfig() : render::Task::Config(false) {} - - float size{ 0.7f }; - - void setIntensity(float value); - float getIntensity() const; - void setSize(float value); - -signals: - void dirty(); }; class BloomThresholdConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) - -public: - - float threshold{ 0.9f }; - -signals: - void dirty(); }; class BloomThreshold { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using Outputs = gpu::FramebufferPointer; using Config = BloomThresholdConfig; using JobModel = render::Job::ModelIO; @@ -71,21 +50,11 @@ private: class BloomApplyConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) - Q_PROPERTY(float sigma MEMBER sigma NOTIFY dirty) - -public: - - float intensity{ 0.25f }; - float sigma{ 1.0f }; - -signals: - void dirty(); }; class BloomApply { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet5; using Config = BloomApplyConfig; using JobModel = render::Job::ModelI; @@ -118,7 +87,7 @@ private: class DebugBloomConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) + Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) public: @@ -155,13 +124,13 @@ private: DebugBloomConfig::Mode _mode; }; -class Bloom { +class BloomEffect { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet3; using Config = BloomConfig; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelI; - Bloom(); + BloomEffect(); void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); diff --git a/libraries/render-utils/src/BloomStage.cpp b/libraries/render-utils/src/BloomStage.cpp new file mode 100644 index 0000000000..9a1c8ee183 --- /dev/null +++ b/libraries/render-utils/src/BloomStage.cpp @@ -0,0 +1,80 @@ +// +// BloomStage.cpp +// +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "BloomStage.h" + +#include "DeferredLightingEffect.h" + +#include + +std::string BloomStage::_stageName { "BLOOM_STAGE"}; +const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + +FetchBloomStage::FetchBloomStage() { + _bloom = std::make_shared(); +} + +void FetchBloomStage::configure(const Config& config) { + _bloom->setBloomIntensity(config.bloomIntensity); + _bloom->setBloomThreshold(config.bloomThreshold); + _bloom->setBloomSize(config.bloomSize); + _bloom->setBloomActive(config.isBloomActive); +} + +BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const { + auto found = _bloomMap.find(bloom); + if (found != _bloomMap.end()) { + return INVALID_INDEX; + } else { + return (*found).second; + } +} + +BloomStage::Index BloomStage::addBloom(const BloomPointer& bloom) { + auto found = _bloomMap.find(bloom); + if (found == _bloomMap.end()) { + auto bloomId = _blooms.newElement(bloom); + // Avoid failing to allocate a bloom, just pass + if (bloomId != INVALID_INDEX) { + // Insert the bloom and its index in the reverse map + _bloomMap.insert(BloomMap::value_type(bloom, bloomId)); + } + return bloomId; + } else { + return (*found).second; + } +} + +BloomStage::BloomPointer BloomStage::removeBloom(Index index) { + BloomPointer removed = _blooms.freeElement(index); + if (removed) { + _bloomMap.erase(removed); + } + return removed; +} + +BloomStageSetup::BloomStageSetup() {} + +void BloomStageSetup::run(const render::RenderContextPointer& renderContext) { + auto stage = renderContext->_scene->getStage(BloomStage::getName()); + if (!stage) { + renderContext->_scene->resetStage(BloomStage::getName(), std::make_shared()); + } +} + +void FetchBloomStage::run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom) { + auto bloomStage = renderContext->_scene->getStage(); + assert(bloomStage); + + bloom = nullptr; + if (bloomStage->_currentFrame._blooms.size() != 0) { + auto bloomId = bloomStage->_currentFrame._blooms.front(); + bloom = bloomStage->getBloom(bloomId); + } +} diff --git a/libraries/render-utils/src/BloomStage.h b/libraries/render-utils/src/BloomStage.h new file mode 100644 index 0000000000..76829a19a6 --- /dev/null +++ b/libraries/render-utils/src/BloomStage.h @@ -0,0 +1,122 @@ +// +// BloomStage.h + +// Created by Sam Gondelman on 8/7/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_utils_BloomStage_h +#define hifi_render_utils_BloomStage_h + +#include +#include +#include +#include +#include + +#include +#include +#include + +// Bloom stage to set up bloom-related rendering tasks +class BloomStage : 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 BloomPointer = graphics::BloomPointer; + using Blooms = render::indexed_container::IndexedPointerVector; + using BloomMap = std::unordered_map; + + using BloomIndices = std::vector; + + Index findBloom(const BloomPointer& bloom) const; + Index addBloom(const BloomPointer& bloom); + + BloomPointer removeBloom(Index index); + + bool checkBloomId(Index index) const { return _blooms.checkIndex(index); } + + Index getNumBlooms() const { return _blooms.getNumElements(); } + Index getNumFreeBlooms() const { return _blooms.getNumFreeIndices(); } + Index getNumAllocatedBlooms() const { return _blooms.getNumAllocatedIndices(); } + + BloomPointer getBloom(Index bloomId) const { + return _blooms.get(bloomId); + } + + Blooms _blooms; + BloomMap _bloomMap; + + class Frame { + public: + Frame() {} + + void clear() { _blooms.clear(); } + + void pushBloom(BloomStage::Index index) { _blooms.emplace_back(index); } + + BloomStage::BloomIndices _blooms; + }; + + Frame _currentFrame; +}; +using BloomStagePointer = std::shared_ptr; + +class BloomStageSetup { +public: + using JobModel = render::Job::Model; + + BloomStageSetup(); + void run(const render::RenderContextPointer& renderContext); + +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); + Q_PROPERTY(bool isBloomActive MEMBER isBloomActive WRITE setBloomActive 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 }; + + bool isBloomActive { false }; + +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(); } + void setBloomActive(const bool active) { isBloomActive = active; emit dirty(); } + +signals: + void dirty(); +}; + +class FetchBloomStage { +public: + using Config = FetchBloomConfig; + using JobModel = render::Job::ModelO; + + FetchBloomStage(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom); + +private: + graphics::BloomPointer _bloom; +}; +#endif diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 8f137cb280..b48168e376 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -163,6 +163,5 @@ public: private: graphics::HazePointer _haze; - gpu::PipelinePointer _hazePipeline; }; #endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 59c86acd19..49851524cd 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -45,6 +45,7 @@ #include "TextureCache.h" #include "ZoneRenderer.h" #include "FadeEffect.h" +#include "BloomStage.h" #include "RenderUtilsLogging.h" #include "AmbientOcclusionEffect.h" @@ -171,7 +172,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto velocityBufferOutputs = task.addJob("VelocityBuffer", velocityBufferInputs); const auto velocityBuffer = velocityBufferOutputs.getN(0); - // Clear Light, Haze and Skybox Stages and render zones from the general metas bucket + // Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket const auto zones = task.addJob("ZoneRenderer", metas); // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. @@ -184,6 +185,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Add haze model const auto hazeModel = task.addJob("HazeModel"); + // Add Bloom model + const auto bloomModel = task.addJob("BloomModel"); // DeferredBuffer is complete, now let's shade it into the LightingBuffer const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, @@ -240,8 +243,8 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("Antialiasing", antialiasingInputs); // Add bloom - const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying(); - task.addJob("Bloom", bloomInputs); + const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomModel).asVarying(); + task.addJob("Bloom", bloomInputs); // Lighting Buffer ready for tone mapping const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying(); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index e05f28ef0d..be61953073 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -14,6 +14,7 @@ #include "LightStage.h" #include "BackgroundStage.h" #include "HazeStage.h" +#include "BloomStage.h" #include #include #include "DeferredLightingEffect.h" @@ -22,6 +23,7 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("LightStageSetup"); task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); + task.addJob("BloomStageSetup"); task.addJob("TransitionStageSetup"); task.addJob("HighlightStageSetup"); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 3299b0c41c..d85818a21a 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -21,11 +21,12 @@ #include "StencilMaskPass.h" #include "DeferredLightingEffect.h" - #include "render-utils/ShaderConstants.h" #include "StencilMaskPass.h" #include "DeferredLightingEffect.h" +#include "BloomStage.h" + namespace ru { using render_utils::slot::texture::Texture; using render_utils::slot::buffer::Buffer; @@ -63,7 +64,7 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu } void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { - // Grab light, background and haze stages and clear them + // Grab light, background, haze, and bloom stages and clear them auto lightStage = context->_scene->getStage(); assert(lightStage); lightStage->_currentFrame.clear(); @@ -76,6 +77,10 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) assert(hazeStage); hazeStage->_currentFrame.clear(); + auto bloomStage = context->_scene->getStage(); + assert(bloomStage); + bloomStage->_currentFrame.clear(); + // call render over the zones to grab their components in the correct order first... render::renderItems(context, inputs); @@ -84,6 +89,7 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight()); backgroundStage->_currentFrame.pushBackground(0); hazeStage->_currentFrame.pushHaze(0); + bloomStage->_currentFrame.pushBloom(0); } const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 9614f8b8fe..744150253d 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -678,6 +678,52 @@
+
+ + Bloom + +
+ Inherit + Off + On +
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d2cea2d394..43ea6bf22f 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -839,7 +839,7 @@ function loaded() { var elZoneHazeModeInherit = document.getElementById("property-zone-haze-mode-inherit"); var elZoneHazeModeDisabled = document.getElementById("property-zone-haze-mode-disabled"); var elZoneHazeModeEnabled = document.getElementById("property-zone-haze-mode-enabled"); - + var elZoneHazeRange = document.getElementById("property-zone-haze-range"); var elZoneHazeColor = document.getElementById("property-zone-haze-color"); var elZoneHazeColorRed = document.getElementById("property-zone-haze-color-red"); @@ -858,6 +858,15 @@ function loaded() { var elZoneHazeBackgroundBlend = document.getElementById("property-zone-haze-background-blend"); + // Bloom + var elZoneBloomModeInherit = document.getElementById("property-zone-bloom-mode-inherit"); + var elZoneBloomModeDisabled = document.getElementById("property-zone-bloom-mode-disabled"); + var elZoneBloomModeEnabled = document.getElementById("property-zone-bloom-mode-enabled"); + + var elZoneBloomIntensity = document.getElementById("property-zone-bloom-intensity"); + var elZoneBloomThreshold = document.getElementById("property-zone-bloom-threshold"); + var elZoneBloomSize = document.getElementById("property-zone-bloom-size"); + var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color"); var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red"); var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green"); @@ -914,19 +923,19 @@ function loaded() { deleteJSONMaterialEditor(); } } - + elTypeIcon.style.display = "none"; elType.innerHTML = "No selection"; elPropertiesList.className = ''; - + elID.value = ""; elName.value = ""; elLocked.checked = false; elVisible.checked = false; - + elParentID.value = ""; elParentJointIndex.value = ""; - + elColorRed.value = ""; elColorGreen.value = ""; elColorBlue.value = ""; @@ -935,15 +944,15 @@ function loaded() { elPositionX.value = ""; elPositionY.value = ""; elPositionZ.value = ""; - + elRotationX.value = ""; elRotationY.value = ""; elRotationZ.value = ""; - + elDimensionsX.value = ""; elDimensionsY.value = ""; elDimensionsZ.value = ""; - + elRegistrationX.value = ""; elRegistrationY.value = ""; elRegistrationZ.value = ""; @@ -965,14 +974,14 @@ function loaded() { elAccelerationX.value = ""; elAccelerationY.value = ""; elAccelerationZ.value = ""; - + elRestitution.value = ""; elFriction.value = ""; elDensity.value = ""; - + elCollisionless.checked = false; elDynamic.checked = false; - + elCollideStatic.checked = false; elCollideKinematic.checked = false; elCollideDynamic.checked = false; @@ -989,27 +998,27 @@ function loaded() { elCloneableGroup.style.display = "none"; elCloneableLimit.value = ""; elCloneableLifetime.value = ""; - - showElements(document.getElementsByClassName('can-cast-shadow-section'), true); + + showElements(document.getElementsByClassName('can-cast-shadow-section'), true); elCanCastShadow.checked = false; - + elCollisionSoundURL.value = ""; elLifetime.value = ""; elScriptURL.value = ""; elServerScripts.value = ""; elHyperlinkHref.value = ""; elDescription.value = ""; - + deleteJSONEditor(); elUserData.value = ""; showUserDataTextArea(); showSaveUserDataButton(); showNewJSONEditorButton(); - + // Shape Properties elShape.value = "Cube"; setDropdownText(elShape); - + // Light Properties elLightSpotLight.checked = false; elLightColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; @@ -1020,7 +1029,7 @@ function loaded() { elLightFalloffRadius.value = ""; elLightExponent.value = ""; elLightCutoff.value = ""; - + // Model Properties elModelURL.value = ""; elCompoundShapeURL.value = ""; @@ -1037,7 +1046,7 @@ function loaded() { elModelAnimationAllowTranslation.checked = false; elModelTextures.value = ""; elModelOriginalTextures.value = ""; - + // Zone Properties elZoneFlyingAllowed.checked = false; elZoneGhostingAllowed.checked = false; @@ -1067,6 +1076,9 @@ function loaded() { elZoneHazeAltitudeEffect.checked = false; elZoneHazeBaseRef.value = ""; elZoneHazeCeiling.value = ""; + elZoneBloomIntensity.value = ""; + elZoneBloomThreshold.value = ""; + elZoneBloomSize.value = ""; elZoneSkyboxColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; elZoneSkyboxColorRed.value = ""; elZoneSkyboxColorGreen.value = ""; @@ -1076,7 +1088,8 @@ function loaded() { showElements(document.getElementsByClassName('skybox-section'), true); showElements(document.getElementsByClassName('ambient-section'), true); showElements(document.getElementsByClassName('haze-section'), true); - + showElements(document.getElementsByClassName('bloom-section'), true); + // Text Properties elTextText.value = ""; elTextLineHeight.value = ""; @@ -1089,14 +1102,14 @@ function loaded() { elTextBackgroundColorRed.value = ""; elTextBackgroundColorGreen.value = ""; elTextBackgroundColorBlue.value = ""; - + // Image Properties elImageURL.value = ""; - + // Web Properties elWebSourceURL.value = ""; elWebDPI.value = ""; - + // Material Properties elMaterialURL.value = ""; elParentMaterialNameNumber.value = ""; @@ -1107,13 +1120,13 @@ function loaded() { elMaterialMappingScaleX.value = ""; elMaterialMappingScaleY.value = ""; elMaterialMappingRot.value = ""; - + deleteJSONMaterialEditor(); elMaterialData.value = ""; showMaterialDataTextArea(); showSaveMaterialDataButton(); showNewJSONMaterialEditorButton(); - + disableProperties(); } else if (data.selections.length > 1) { deleteJSONEditor(); @@ -1250,7 +1263,7 @@ function loaded() { elCloneableGroup.style.display = elCloneable.checked ? "block": "none"; elCloneableLimit.value = properties.cloneLimit; elCloneableLifetime.value = properties.cloneLifetime; - + var grabbablesSet = false; var parsedUserData = {}; try { @@ -1476,6 +1489,14 @@ function loaded() { elZoneHazeBaseRef.value = properties.haze.hazeBaseRef.toFixed(0); elZoneHazeCeiling.value = properties.haze.hazeCeiling.toFixed(0); + elZoneBloomModeInherit.checked = (properties.bloomMode === 'inherit'); + elZoneBloomModeDisabled.checked = (properties.bloomMode === 'disabled'); + elZoneBloomModeEnabled.checked = (properties.bloomMode === 'enabled'); + + elZoneBloomIntensity.value = properties.bloom.bloomIntensity.toFixed(2); + elZoneBloomThreshold.value = properties.bloom.bloomThreshold.toFixed(2); + elZoneBloomSize.value = properties.bloom.bloomSize.toFixed(2); + elShapeType.value = properties.shapeType; elCompoundShapeURL.value = properties.compoundShapeURL; @@ -1502,6 +1523,9 @@ function loaded() { showElements(document.getElementsByClassName('haze-section'), elZoneHazeModeEnabled.checked); + + showElements(document.getElementsByClassName('bloom-section'), + elZoneBloomModeEnabled.checked); } else if (properties.type === "PolyVox") { elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2); elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2); @@ -2067,6 +2091,18 @@ function loaded() { elZoneHazeBackgroundBlend.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeBackgroundBlend')); + // Bloom + var bloomModeChanged = createZoneComponentModeChangedFunction('bloomMode', + elZoneBloomModeInherit, elZoneBloomModeDisabled, elZoneBloomModeEnabled); + + elZoneBloomModeInherit.addEventListener('change', bloomModeChanged); + elZoneBloomModeDisabled.addEventListener('change', bloomModeChanged); + elZoneBloomModeEnabled.addEventListener('change', bloomModeChanged); + + elZoneBloomIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomIntensity')); + elZoneBloomThreshold.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomThreshold')); + elZoneBloomSize.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomSize')); + var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox', 'color', elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue); elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction);