From 55fafeacb15fc150562a2043b106039f4aef8e0f Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 27 Sep 2017 17:43:09 -0700 Subject: [PATCH] Implemented HazePropertyGroup and added the haze shader. Shader does not work yet! --- .../src/RenderableZoneEntityItem.cpp | 1 + .../src/RenderableZoneEntityItem.h | 1 + .../entities/src/EntityItemProperties.cpp | 4 +- libraries/entities/src/EntityItemProperties.h | 4 +- libraries/entities/src/EntityPropertyFlags.h | 17 +- libraries/entities/src/HazePropertyGroup.cpp | 255 ++++++++++++++++-- libraries/entities/src/HazePropertyGroup.h | 37 ++- libraries/model/src/model/Haze.h | 92 ++++--- libraries/render-utils/src/DrawHaze.cpp | 151 +++++++++++ libraries/render-utils/src/DrawHaze.h | 95 +++++++ libraries/render-utils/src/Haze.slf | 143 ++++++++++ libraries/render-utils/src/Haze.slh | 44 +++ libraries/render-utils/src/HazeStage.cpp | 11 +- libraries/render-utils/src/HazeStage.h | 14 +- .../render-utils/src/RenderDeferredTask.cpp | 13 +- .../src/directional_skybox_light.slf | 2 +- 16 files changed, 798 insertions(+), 86 deletions(-) create mode 100644 libraries/render-utils/src/DrawHaze.cpp create mode 100644 libraries/render-utils/src/DrawHaze.h create mode 100644 libraries/render-utils/src/Haze.slf create mode 100644 libraries/render-utils/src/Haze.slh diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 8b0a7e9f88..6ee0e86fe8 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -60,6 +60,7 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity } } +#pragma optimize("", off); void ZoneEntityRenderer::doRender(RenderArgs* args) { #if 0 if (ZoneEntityItem::getDrawZoneBoundaries()) { diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index c955e07d11..26403a2483 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -81,6 +81,7 @@ private: const model::LightPointer _ambientLight{ std::make_shared() }; const model::SunSkyStagePointer _background{ std::make_shared() }; const model::HazePointer _haze{ std::make_shared() }; + BackgroundMode _backgroundMode{ BACKGROUND_MODE_INHERIT }; HazeMode _hazeMode{ HAZE_MODE_INHERIT }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c2a0f67a61..868f5a6dd7 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1073,8 +1073,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); - ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_HAZE_RANGE, Haze, haze, HazeRange, hazeRange); - ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_HAZE_ALTITUDE, Haze, haze, HazeAltitude, hazeAltitude); + ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_RANGE, Haze, haze, HazeRange, hazeRange); + ADD_GROUP_PROPERTY_TO_MAP(PROP_HAZE_ALTITUDE, Haze, haze, HazeAltitude, hazeAltitude); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled); ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index bbc3a2e753..25799fcc0c 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -180,8 +180,8 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_BACKGROUND_MODE, BackgroundMode, backgroundMode, BackgroundMode, BACKGROUND_MODE_INHERIT); DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, HazeMode, HAZE_MODE_INHERIT); - DEFINE_PROPERTY(PROP_HAZE_HAZE_RANGE, HazeRange, hazeRange, float, HazePropertyGroup::DEFAULT_HAZE_RANGE); - DEFINE_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, HazeAltitude, hazeAltitude, float, HazePropertyGroup::DEFAULT_HAZE_ALTITUDE); + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, HazePropertyGroup::DEFAULT_HAZE_RANGE); + DEFINE_PROPERTY(PROP_HAZE_ALTITUDE, HazeAltitude, hazeAltitude, float, HazePropertyGroup::DEFAULT_HAZE_ALTITUDE); DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup); DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index e3076e57ee..46fb31d7aa 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -219,9 +219,22 @@ enum EntityPropertyList { PROP_STAGE_HOUR = PROP_QUADRATIC_ATTENUATION_UNUSED, PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX, PROP_BACKGROUND_MODE = PROP_MODEL_URL, + PROP_HAZE_MODE = PROP_COLOR, - PROP_HAZE_HAZE_RANGE = PROP_INTENSITY, - PROP_HAZE_HAZE_ALTITUDE = PROP_CUTOFF, + + PROP_HAZE_RANGE = PROP_INTENSITY, + PROP_HAZE_BLEND_IN_COLOR = PROP_CUTOFF, + PROP_HAZE_BLEND_OUT_COLOR = PROP_EXPONENT, + PROP_HAZE_LIGHT_BLEND_ANGLE = PROP_IS_SPOTLIGHT, + + PROP_HAZE_ALTITUDE = PROP_DIFFUSE_COLOR, + PROP_HAZE_BASE_REF = PROP_AMBIENT_COLOR_UNUSED, + + PROP_HAZE_BACKGROUND_BLEND = PROP_SPECULAR_COLOR_UNUSED, + + PROP_HAZE_KEYLIGHT_RANGE = PROP_LINEAR_ATTENUATION_UNUSED, + PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_QUADRATIC_ATTENUATION_UNUSED, + PROP_SKYBOX_COLOR = PROP_ANIMATION_URL, PROP_SKYBOX_URL = PROP_ANIMATION_FPS, PROP_KEYLIGHT_AMBIENT_URL = PROP_ANIMATION_PLAYING, diff --git a/libraries/entities/src/HazePropertyGroup.cpp b/libraries/entities/src/HazePropertyGroup.cpp index 205a1a2765..fa7278b2d3 100644 --- a/libraries/entities/src/HazePropertyGroup.cpp +++ b/libraries/entities/src/HazePropertyGroup.cpp @@ -15,41 +15,125 @@ #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" -const float HazePropertyGroup::DEFAULT_HAZE_RANGE = 1000.0f; -const float HazePropertyGroup::DEFAULT_HAZE_ALTITUDE = 200.0f; +const uint8_t HazePropertyGroup::DEFAULT_HAZE_MODE{ 0 }; + +const float HazePropertyGroup::DEFAULT_HAZE_RANGE{ 1000.0f }; +const xColor HazePropertyGroup::DEFAULT_HAZE_BLEND_IN_COLOR{ 128, 154, 179 }; // Bluish +const xColor HazePropertyGroup::DEFAULT_HAZE_BLEND_OUT_COLOR{ 255, 229, 179 }; // Yellowish +const float HazePropertyGroup::DEFAULT_LIGHT_BLEND_ANGLE{ 20.0 }; + +const float HazePropertyGroup::DEFAULT_HAZE_ALTITUDE{ 200.0f }; +const float HazePropertyGroup::DEFAULT_HAZE_BASE_REF{ 0.0f }; + +const float HazePropertyGroup::DEFAULT_HAZE_BACKGROUND_BLEND{ 0.0f }; + +const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_RANGE{ 1000.0 }; +const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_ALTITUDE{ 200.0f }; void HazePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { - COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_HAZE_RANGE, Haze, haze, HazeRange, hazeRange); - COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_HAZE_ALTITUDE, Haze, haze, HazeAltitude, hazeAltitude); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_MODE, Haze, haze, HazeMode, hazeMode); + + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_BLEND_IN_COLOR, Haze, haze, HazeRange, hazeRange); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_BLEND_IN_COLOR, Haze, haze, HazeBlendInColor, hazeBlendIncolor); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_BLEND_OUT_COLOR, Haze, haze, HazeBlendOutColor, hazeBlendOutcolor); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_LIGHT_BLEND_ANGLE, Haze, haze, HazeLightBlendAngle, hazeLightBlendAngle); + + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_ALTITUDE, Haze, haze, HazeAltitude, hazeAltitude); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_BASE_REF, Haze, haze, HazeBaseRef, hazeBaseRef); + + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_BACKGROUND_BLEND, Haze, haze, HazeBackgroundBlend, hazeBackgroundBlend); + + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_KEYLIGHT_RANGE, Haze, haze, HazeKeyLightRange, hazeKeyLightRange); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_KEYLIGHT_ALTITUDE, Haze, haze, HazeKeyLightAltitude, hazeKeyLightAltitude); } void HazePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { - COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeRange, float, setHazeRange, getHazeRange); - COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeAltitude, float, setHazeAltitude, getHazeAltitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeMode, uint8_t, setHazeMode, getHazeMode); - COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(haze, hazeRange, float, setHazeRange); - COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(haze, hazeAltitude, float, setHazeAltitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeRange, float, setHazeRange, getHazeRange); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(haze, hazeBlendInColor, xColor, setHazeBlendInColor); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(haze, hazeBlendOutColor, xColor, setHazeBlendOutColor); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeLightBlendAngle, float, setHazeLightBlendAngle, getHazeLightBlendAngle); + + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeAltitude, float, setHazeAltitude, getHazeAltitude); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeBaseRef, float, setHazeBaseRef, getHazeBaseRef); + + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeBackgroundBlend, float, setHazeBackgroundBlend, getHazeBackgroundBlend); + + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeKeyLightRange, float, setHazeKeyLightRange, getHazeKeyLightRange); + COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(hazeHazeKeyLightAltitude, float, setHazeKeyLightAltitude, getHazeKeyLightAltitude); } void HazePropertyGroup::merge(const HazePropertyGroup& other) { - COPY_PROPERTY_IF_CHANGED(hazeRange); - COPY_PROPERTY_IF_CHANGED(hazeAltitude); -} + COPY_PROPERTY_IF_CHANGED(hazeMode); + COPY_PROPERTY_IF_CHANGED(hazeRange); + COPY_PROPERTY_IF_CHANGED(hazeBlendInColor); + COPY_PROPERTY_IF_CHANGED(hazeBlendOutColor); + COPY_PROPERTY_IF_CHANGED(hazeLightBlendAngle); + + COPY_PROPERTY_IF_CHANGED(hazeAltitude); + COPY_PROPERTY_IF_CHANGED(hazeBaseRef); + + COPY_PROPERTY_IF_CHANGED(hazeBackgroundBlend); + + COPY_PROPERTY_IF_CHANGED(hazeKeyLightRange); + COPY_PROPERTY_IF_CHANGED(hazeKeyLightAltitude); +} void HazePropertyGroup::debugDump() const { qCDebug(entities) << " HazePropertyGroup: ---------------------------------------------"; + qCDebug(entities) << " _hazeMode:" << _hazeMode; + qCDebug(entities) << " _hazeRange:" << _hazeRange; + qCDebug(entities) << " _hazeBlendInColor:" << _hazeBlendInColor; + qCDebug(entities) << " _hazeBlendOutColor:" << _hazeBlendInColor; + qCDebug(entities) << " _hazeLightBlendAngle:" << _hazeLightBlendAngle; + qCDebug(entities) << " _hazeAltitude:" << _hazeAltitude; + qCDebug(entities) << " _hazeBaseRef:" << _hazeBaseRef; + + qCDebug(entities) << " _hazeBackgroundBlend:" << _hazeBackgroundBlend; + + qCDebug(entities) << " _hazeKeyLightRange:" << _hazeKeyLightRange; + qCDebug(entities) << " _hazeKeyLightAltitude:" << _hazeKeyLightAltitude; } void HazePropertyGroup::listChangedProperties(QList& out) { + if (hazeModeChanged()) { + out << "haze-mode"; + } + if (hazeRangeChanged()) { out << "haze-range"; } + if (hazeBlendInColorChanged()) { + out << "haze-blendInColor"; + } + if (hazeBlendOutColorChanged()) { + out << "haze-blendOutColor"; + } + if (hazeLightBlendAngleChanged()) { + out << "haze-lightBlendAngle"; + } + if (hazeAltitudeChanged()) { out << "haze-altitude"; } + if (hazeBaseRefChanged()) { + out << "haze-baseRef"; + } + + if (hazeBackgroundBlendChanged()) { + out << "haze-backgroundBlend"; + } + + if (hazeKeyLightRangeChanged()) { + out << "haze-keyLightRange"; + } + if (hazeKeyLightAltitudeChanged()) { + out << "haze-keyLightAltitude"; + } } bool HazePropertyGroup::appendToEditPacket(OctreePacketData* packetData, @@ -61,24 +145,59 @@ bool HazePropertyGroup::appendToEditPacket(OctreePacketData* packetData, bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_HAZE_HAZE_RANGE, getHazeRange()); - APPEND_ENTITY_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, getHazeAltitude()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, getHazeMode()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_RANGE, getHazeRange()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BLEND_IN_COLOR, getHazeBlendInColor()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BLEND_OUT_COLOR, getHazeBlendOutColor()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_LIGHT_BLEND_ANGLE, getHazeLightBlendAngle()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_ALTITUDE, getHazeAltitude()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BASE_REF, getHazeBaseRef()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_BACKGROUND_BLEND, getHazeBackgroundBlend()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_RANGE, getHazeKeyLightRange()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_ALTITUDE, getHazeKeyLightAltitude()); return true; } - bool HazePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) { int bytesRead = 0; bool overwriteLocalData = true; bool somethingChanged = false; - READ_ENTITY_PROPERTY(PROP_HAZE_HAZE_RANGE, float, setHazeRange); - READ_ENTITY_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, float, setHazeAltitude); + READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint8_t, setHazeMode); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_HAZE_RANGE, HazeRange); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_HAZE_ALTITUDE, HazeAltitude); + READ_ENTITY_PROPERTY(PROP_HAZE_RANGE, float, setHazeRange); + READ_ENTITY_PROPERTY(PROP_HAZE_BLEND_IN_COLOR, xColor, setHazeBlendInColor); + READ_ENTITY_PROPERTY(PROP_HAZE_BLEND_OUT_COLOR, xColor, setHazeBlendOutColor); + READ_ENTITY_PROPERTY(PROP_HAZE_LIGHT_BLEND_ANGLE, float, setHazeLightBlendAngle); + + READ_ENTITY_PROPERTY(PROP_HAZE_ALTITUDE, float, setHazeAltitude); + READ_ENTITY_PROPERTY(PROP_HAZE_BASE_REF, float, setHazeBaseRef); + + READ_ENTITY_PROPERTY(PROP_HAZE_BACKGROUND_BLEND, float, setHazeBackgroundBlend); + + READ_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_RANGE, float, setHazeKeyLightRange); + READ_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_ALTITUDE, float, setHazeKeyLightAltitude); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_RANGE, HazeMode); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_RANGE, HazeRange); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_BLEND_IN_COLOR, HazeBlendInColor); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_BLEND_OUT_COLOR, HazeBlendOutColor); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_LIGHT_BLEND_ANGLE, HazeLightBlendAngle); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_ALTITUDE, HazeAltitude); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_BASE_REF, HazeBaseRef); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude); processedBytes += bytesRead; @@ -88,29 +207,77 @@ bool HazePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, } void HazePropertyGroup::markAllChanged() { + _hazeModeChanged; + _hazeRangeChanged = true; + _hazeBlendInColorChanged = true; + _hazeBlendOutColorChanged = true; + _hazeLightBlendAngleChanged = true; + + _hazeAltitudeChanged = true; + _hazeBaseRefChanged = true; + + _hazeBackgroundBlendChanged = true; + + _hazeKeyLightRangeChanged = true; _hazeAltitudeChanged = true; } EntityPropertyFlags HazePropertyGroup::getChangedProperties() const { EntityPropertyFlags changedProperties; - CHECK_PROPERTY_CHANGE(PROP_HAZE_HAZE_RANGE, hazeRange); - CHECK_PROPERTY_CHANGE(PROP_HAZE_HAZE_ALTITUDE, hazeAltitude); + CHECK_PROPERTY_CHANGE(PROP_HAZE_MODE, hazeMode); + + CHECK_PROPERTY_CHANGE(PROP_HAZE_RANGE, hazeRange); + CHECK_PROPERTY_CHANGE(PROP_HAZE_BLEND_IN_COLOR, hazeBlendInColor); + CHECK_PROPERTY_CHANGE(PROP_HAZE_BLEND_OUT_COLOR, hazeBlendOutColor); + CHECK_PROPERTY_CHANGE(PROP_HAZE_LIGHT_BLEND_ANGLE, hazeLightBlendAngle); + + CHECK_PROPERTY_CHANGE(PROP_HAZE_ALTITUDE, hazeAltitude); + CHECK_PROPERTY_CHANGE(PROP_HAZE_BASE_REF, hazeBaseRef); + + CHECK_PROPERTY_CHANGE(PROP_HAZE_BACKGROUND_BLEND, hazeBackgroundBlend); + + CHECK_PROPERTY_CHANGE(PROP_HAZE_KEYLIGHT_RANGE, hazeKeyLightRange); + CHECK_PROPERTY_CHANGE(PROP_HAZE_KEYLIGHT_ALTITUDE, hazeKeyLightAltitude); return changedProperties; } void HazePropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeMode, getHazeMode); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeRange, getHazeRange); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeBlendInColor, getHazeBlendInColor); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeBlendOutColor, getHazeBlendOutColor); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeLightBlendAngle, getHazeLightBlendAngle); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeAltitude, getHazeAltitude); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeBaseRef, getHazeBaseRef); + + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeBackgroundBlend, getHazeBackgroundBlend); + + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeKeyLightRange, getHazeKeyLightRange); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Haze, HazeKeyLightAltitude, getHazeKeyLightAltitude); } bool HazePropertyGroup::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeMode, hazeMode, setHazeMode); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeRange, hazeRange, setHazeRange); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeBlendInColor, hazeBlendInColor, setHazeBlendInColor); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeBlendOutColor, hazeBlendOutColor, setHazeBlendOutColor); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeLightBlendAngle, hazeLightBlendAngle, setHazeLightBlendAngle); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeAltitude, hazeAltitude, setHazeAltitude); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeBaseRef, hazeBaseRef, setHazeBaseRef); + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeBackgroundBlend, hazeBackgroundBlend, setHazeBackgroundBlend); + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeKeyLightRange, hazeKeyLightRange, setHazeKeyLightRange); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Haze, HazeKeyLightAltitude, hazeKeyLightAltitude, setHazeKeyLightAltitude); return somethingChanged; } @@ -118,8 +285,20 @@ bool HazePropertyGroup::setProperties(const EntityItemProperties& properties) { EntityPropertyFlags HazePropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties; - requestedProperties += PROP_HAZE_HAZE_RANGE; - requestedProperties += PROP_HAZE_HAZE_ALTITUDE; + requestedProperties += PROP_HAZE_MODE; + + requestedProperties += PROP_HAZE_RANGE; + requestedProperties += PROP_HAZE_BLEND_IN_COLOR; + requestedProperties += PROP_HAZE_BLEND_OUT_COLOR; + requestedProperties += PROP_HAZE_LIGHT_BLEND_ANGLE; + + requestedProperties += PROP_HAZE_ALTITUDE; + requestedProperties += PROP_HAZE_BASE_REF; + + requestedProperties += PROP_HAZE_BACKGROUND_BLEND; + + requestedProperties += PROP_HAZE_KEYLIGHT_RANGE; + requestedProperties += PROP_HAZE_KEYLIGHT_ALTITUDE; return requestedProperties; } @@ -134,8 +313,20 @@ void HazePropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeB bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_HAZE_HAZE_RANGE, getHazeRange()); - APPEND_ENTITY_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, getHazeAltitude()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_MODE, getHazeMode()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_RANGE, getHazeRange()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BLEND_IN_COLOR, getHazeBlendInColor()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BLEND_OUT_COLOR, getHazeBlendOutColor()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_LIGHT_BLEND_ANGLE, getHazeLightBlendAngle()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_ALTITUDE, getHazeAltitude()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_BASE_REF, getHazeBaseRef()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_BACKGROUND_BLEND, getHazeBackgroundBlend()); + + APPEND_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_RANGE, getHazeKeyLightRange()); + APPEND_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_ALTITUDE, getHazeKeyLightAltitude()); } int HazePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -146,8 +337,20 @@ int HazePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* dat int bytesRead = 0; const unsigned char* dataAt = data; - READ_ENTITY_PROPERTY(PROP_HAZE_HAZE_RANGE, float, setHazeRange); - READ_ENTITY_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, float, setHazeAltitude); + READ_ENTITY_PROPERTY(PROP_HAZE_MODE, uint8_t, setHazeMode); + + READ_ENTITY_PROPERTY(PROP_HAZE_RANGE, float, setHazeRange); + READ_ENTITY_PROPERTY(PROP_HAZE_BLEND_IN_COLOR, xColor, setHazeBlendInColor); + READ_ENTITY_PROPERTY(PROP_HAZE_BLEND_OUT_COLOR, xColor, setHazeBlendOutColor); + READ_ENTITY_PROPERTY(PROP_HAZE_LIGHT_BLEND_ANGLE, float, setHazeLightBlendAngle); + + READ_ENTITY_PROPERTY(PROP_HAZE_ALTITUDE, float, setHazeAltitude); + READ_ENTITY_PROPERTY(PROP_HAZE_BASE_REF, float, setHazeBaseRef); + + READ_ENTITY_PROPERTY(PROP_HAZE_BACKGROUND_BLEND, float, setHazeBackgroundBlend); + + READ_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_RANGE, float, setHazeKeyLightRange); + READ_ENTITY_PROPERTY(PROP_HAZE_KEYLIGHT_ALTITUDE, float, setHazeKeyLightAltitude); return bytesRead; } diff --git a/libraries/entities/src/HazePropertyGroup.h b/libraries/entities/src/HazePropertyGroup.h index f5b3f65bcb..78cf1d6e46 100644 --- a/libraries/entities/src/HazePropertyGroup.h +++ b/libraries/entities/src/HazePropertyGroup.h @@ -74,11 +74,40 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - static const float DEFAULT_HAZE_RANGE; - static const float DEFAULT_HAZE_ALTITUDE; + static const uint8_t DEFAULT_HAZE_MODE; - DEFINE_PROPERTY(PROP_HAZE_HAZE_RANGE, HazeRange, hazeRange, float, DEFAULT_HAZE_RANGE); - DEFINE_PROPERTY(PROP_HAZE_HAZE_ALTITUDE, HazeAltitude, hazeAltitude, float, DEFAULT_HAZE_ALTITUDE); + static const float DEFAULT_HAZE_RANGE; + static const xColor DEFAULT_HAZE_BLEND_IN_COLOR; + static const xColor DEFAULT_HAZE_BLEND_OUT_COLOR; + static const float DEFAULT_LIGHT_BLEND_ANGLE; + + static const float DEFAULT_HAZE_ALTITUDE; + static const float DEFAULT_HAZE_BASE_REF; + + static const float DEFAULT_HAZE_BACKGROUND_BLEND; + + static const float DEFAULT_HAZE_KEYLIGHT_RANGE; + static const float DEFAULT_HAZE_KEYLIGHT_ALTITUDE; + + // Selects whether haze inherits the mode, is off or the mode (range only, range & altitude...) + DEFINE_PROPERTY(PROP_HAZE_MODE, HazeMode, hazeMode, uint8_t, DEFAULT_HAZE_MODE); + + // Range only parameters + DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, DEFAULT_HAZE_RANGE); + DEFINE_PROPERTY_REF(PROP_HAZE_BLEND_IN_COLOR, HazeBlendInColor, hazeBlendInColor, xColor, DEFAULT_HAZE_BLEND_IN_COLOR); + DEFINE_PROPERTY_REF(PROP_HAZE_BLEND_OUT_COLOR, HazeBlendOutColor, hazeBlendOutColor, xColor, DEFAULT_HAZE_BLEND_OUT_COLOR); + DEFINE_PROPERTY(PROP_HAZE_LIGHT_BLEND_ANGLE, HazeLightBlendAngle, hazeLightBlendAngle, float, DEFAULT_LIGHT_BLEND_ANGLE); + + // Range & Altitude parameters + DEFINE_PROPERTY(PROP_HAZE_ALTITUDE, HazeAltitude, hazeAltitude, float, DEFAULT_HAZE_ALTITUDE); + DEFINE_PROPERTY(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, DEFAULT_HAZE_BASE_REF); + + // Background (skybox) blend value + DEFINE_PROPERTY(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, DEFAULT_HAZE_BACKGROUND_BLEND); + + // Directional light attenuation + DEFINE_PROPERTY(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, DEFAULT_HAZE_KEYLIGHT_RANGE); + DEFINE_PROPERTY(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, DEFAULT_HAZE_KEYLIGHT_ALTITUDE); }; #endif // hifi_HazePropertyGroup_h diff --git a/libraries/model/src/model/Haze.h b/libraries/model/src/model/Haze.h index 60fa59a5ba..fee387cd0d 100644 --- a/libraries/model/src/model/Haze.h +++ b/libraries/model/src/model/Haze.h @@ -14,49 +14,51 @@ #include #include "NumericalConstants.h" +const double p_005 = 0.05; + +// Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 +// f = exp(-d * b) +// ln(f) = -d * b +// b = -ln(f)/d +inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return (float)-log(p_005) / hazeRange_m; } + +inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { + return (float)-log(p_005) / hazeAltitude_m; +} + +// Derivation (s is th proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 +// s = dot(lookAngle, sunAngle) = cos(a) +// m = pow(s, p) +// log(m) = p * log(s) +// p = log(m) / log(s) +inline float convertDirectionalLightAngleToPower(const float directionalLightAngle) { + return log(0.5) / log(cos(RADIANS_PER_DEGREE * directionalLightAngle)); +} + +const glm::vec3 initialHazeColor{ 0.5, 0.6, 0.7 }; +const float initialDirectionalLightAngle_degs{ 30.0f }; + +const glm::vec3 initialDirectionalLightColor{ 1.0, 0.9, 0.7 }; +const float initialHazeBaseReference{ 0.0f }; + +// Haze range is defined here as the range the visibility is reduced by 95% +// Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95% +const float initialHazeRange_m{ 150.0f }; +const float initialHazeAltitude_m{ 150.0f }; + +const float initialHazeRangeKeyLight_m{ 150.0f }; +const float initialHazeAltitudeKeyLight_m{ 150.0f }; + +const float initialBackgroundBlendValue{ 0.0f }; + +const glm::vec3 initialColorModulationFactor{ + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m), + convertHazeRangeToHazeRangeFactor(initialHazeRange_m) +}; + namespace model { - const double p_005 = 0.05; - - // Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05 - // f = exp(-d * b) - // ln(f) = -d * b - // b = -ln(f)/d - inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return (float)-log(p_005) / hazeRange_m; } - - inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) { - return (float)-log(p_005) / hazeAltitude_m; - } - - // Derivation (s is th proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5 - // s = dot(lookAngle, sunAngle) = cos(a) - // m = pow(s, p) - // log(m) = p * log(s) - // p = log(m) / log(s) - inline float convertDirectionalLightAngleToPower(const float directionalLightAngle) { - return log(0.5) / log(cos(RADIANS_PER_DEGREE * directionalLightAngle)); - } - - const glm::vec3 initialHazeColor{ 0.5, 0.6, 0.7 }; - const float initialDirectionalLightAngle_degs{ 30.0f }; - - const glm::vec3 initialDirectionalLightColor{ 1.0, 0.9, 0.7 }; - const float initialHazeBaseReference{ 0.0f }; - - // Haze range is defined here as the range the visibility is reduced by 95% - // Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95% - const float initialHazeRange_m = 150.0f; - const float initialHazeAltitude_m = 150.0f; - - const float initialHazeRangeKeyLight_m = 150.0f; - const float initialHazeAltitudeKeyLight_m = 150.0f; - - const glm::vec3 initialColorModulationFactor{ - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m), - convertHazeRangeToHazeRangeFactor(initialHazeRange_m) - }; - class Haze { public: using UniformBufferView = gpu::BufferView; @@ -80,6 +82,8 @@ namespace model { void setHazeRangeFactorKeyLight(const float hazeRangeKeyLight); void setHazeAltitudeFactorKeyLight(const float hazeAltitudeKeyLight); + void setBackgroundBlendValue(const float backgroundBlendValue); + UniformBufferView getParametersBuffer() const { return _parametersBuffer; } protected: @@ -97,19 +101,21 @@ namespace model { // bit 1 - set to add the effect of altitude to the haze attenuation // bit 2 - set to activate directional light attenuation mode - // The haze attenuation exponents used by both fragment and directional light attenuation + // The haze attenuation exponents used by both fragment and directional light attenuation float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange_m) }; float hazeAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeAltitude_m) }; float hazeRangeFactorKeyLight{ convertHazeRangeToHazeRangeFactor(initialHazeRangeKeyLight_m) }; float hazeAltitudeFactorKeyLight{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeAltitudeKeyLight_m) }; + float backgroundBlendValue{ initialBackgroundBlendValue }; + Parameters() {} }; UniformBufferView _parametersBuffer; }; - typedef std::shared_ptr HazePointer; + using HazePointer = std::shared_ptr; } #endif // hifi_model_Haze_h diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp new file mode 100644 index 0000000000..33db0c1f6c --- /dev/null +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -0,0 +1,151 @@ +// +// DrawHaze.cpp +// libraries/render-utils/src +// +// Created by Nissim Hadar on 9/1/2017. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "DrawHaze.h" + +#include +#include + +#include "StencilMaskPass.h" +#include "FramebufferCache.h" + +#include "Haze_frag.h" + +void HazeConfig::setHazeColorR(const float value) { + hazeColorR = value; +} + +void HazeConfig::setHazeColorG(const float value) { + hazeColorG = value; +} + +void HazeConfig::setHazeColorB(const float value) { + hazeColorB = value; +} + +void HazeConfig::setDirectionalLightAngle_degs(const float value) { + directionalLightAngle_degs = value; +} + +void HazeConfig::setDirectionalLightColorR(const float value) { + directionalLightColorR = value; +} + +void HazeConfig::setDirectionalLightColorG(const float value) { + directionalLightColorG = value; +} + +void HazeConfig::setDirectionalLightColorB(const float value) { + directionalLightColorB = value; +} + +void HazeConfig::setHazeBaseReference(const float value) { + hazeBaseReference = value; +} + +void HazeConfig::setIsHazeActive(const bool active) { + isHazeActive = active; +} + +void HazeConfig::setIsAltitudeBased(const bool active) { + isAltitudeBased = active; +} + +void HazeConfig::setIsdirectionalLightAttenuationActive(const bool active) { + isDirectionalLightAttenuationActive = active; +} + +void HazeConfig::setIsModulateColorActive(const bool active) { + isModulateColorActive = active; +} + +void HazeConfig::setHazeRange_m(const float value) { + hazeRange_m = value; +} + +void HazeConfig::setHazeAltitude_m(const float value) { + hazeAltitude_m = value; +} + +void HazeConfig::setHazeRangeKeyLight_m(const float value) { + hazeRangeKeyLight_m = value; +} + +void HazeConfig::setHazeAltitudeKeyLight_m(const float value) { + hazeAltitudeKeyLight_m = value; +} + +void HazeConfig::setBackgroundBlendValue(const float value) { + backgroundBlendValue = value; +} + +const int HazeEffect_ParamsSlot = 0; +const int HazeEffect_TransformBufferSlot = 1; + +const int HazeEffect_LightingMapSlot = 2; +const int HazeEffect_LinearDepthMapSlot = 3; + +void DrawHaze::configure(const Config& config) { +} + +void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + const auto haze = inputs.get0(); + const auto inputBuffer = inputs.get1()->getRenderBuffer(0); + const auto framebuffer = inputs.get2(); + const auto transformBuffer = inputs.get3(); + + auto outputBuffer = inputs.get4(); + + auto depthBuffer = framebuffer->getLinearDepthTexture(); + + if (_hazePipeline == nullptr) { + gpu::ShaderPointer ps = gpu::Shader::createPixel(std::string(Haze_frag)); + gpu::ShaderPointer vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + // Mask out haze on the tablet + PrepareStencil::testMaskNoAA(*state); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_LightingMapSlot)); + slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot)); + gpu::Shader::makeProgram(*program, slotBindings); + + _hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + } + + auto sourceFramebufferSize = glm::ivec2(inputBuffer->getDimensions()); + + gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(outputBuffer); + + batch.setViewportTransform(renderContext->args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform( + gpu::Framebuffer::evalSubregionTexcoordTransform(sourceFramebufferSize, renderContext->args->_viewport)); + + batch.setPipeline(_hazePipeline); + +//// batch.setUniformBuffer(HazeEffect_ParamsSlot, haze->getParametersBuffer()); + batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); + + batch.setResourceTexture(HazeEffect_LightingMapSlot, inputBuffer); + batch.setResourceTexture(HazeEffect_LinearDepthMapSlot, depthBuffer); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); +} diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h new file mode 100644 index 0000000000..fc8a9144b3 --- /dev/null +++ b/libraries/render-utils/src/DrawHaze.h @@ -0,0 +1,95 @@ +// +// DrawHaze.h +// libraries/render-utils/src +// +// Created by Nissim Hadar on 9/1/2017. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_utils_DrawHaze_h +#define hifi_render_utils_DrawHaze_h + +#include +#include + +#include +#include +#include +#include + +#include "SurfaceGeometryPass.h" + +#include "model/Haze.h" + +using LinearDepthFramebufferPointer = std::shared_ptr; + +class HazeConfig : public render::Job::Config { +public: + HazeConfig() : render::Job::Config(true) {} + + // attributes + float hazeColorR{ initialHazeColor.r }; + float hazeColorG{ initialHazeColor.g }; + float hazeColorB{ initialHazeColor.b }; + float directionalLightAngle_degs{ initialDirectionalLightAngle_degs }; + + float directionalLightColorR{ initialDirectionalLightColor.r }; + float directionalLightColorG{ initialDirectionalLightColor.g }; + float directionalLightColorB{ initialDirectionalLightColor.b }; + float hazeBaseReference{ initialHazeBaseReference }; + + bool isHazeActive{ false }; // Setting this to true will set haze to on + bool isAltitudeBased{ false }; + bool isDirectionalLightAttenuationActive{ false }; + bool isModulateColorActive{ false }; + + float hazeRange_m{ initialHazeRange_m }; + float hazeAltitude_m{ initialHazeAltitude_m }; + + float hazeRangeKeyLight_m{ initialHazeRangeKeyLight_m }; + float hazeAltitudeKeyLight_m{ initialHazeAltitudeKeyLight_m }; + + float backgroundBlendValue{ initialBackgroundBlendValue }; + + // methods + void setHazeColorR(const float value); + void setHazeColorG(const float value); + void setHazeColorB(const float value); + void setDirectionalLightAngle_degs(const float value); + + void setDirectionalLightColorR(const float value); + void setDirectionalLightColorG(const float value); + void setDirectionalLightColorB(const float value); + void setHazeBaseReference(const float value); + + void setIsHazeActive(const bool active); + void setIsAltitudeBased(const bool active); + void setIsdirectionalLightAttenuationActive(const bool active); + void setIsModulateColorActive(const bool active); + + void setHazeRange_m(const float value); + void setHazeAltitude_m(const float value); + + void setHazeRangeKeyLight_m(const float value); + void setHazeAltitudeKeyLight_m(const float value); + + void setBackgroundBlendValue(const float value); +}; + +class DrawHaze { +public: + using Inputs = render::VaryingSet5; + using Config = HazeConfig; + using JobModel = render::Job::ModelI; + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +private: + gpu::PipelinePointer _hazePipeline; +}; + +#endif // hifi_render_utils_DrawHaze_h diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf new file mode 100644 index 0000000000..b896afde92 --- /dev/null +++ b/libraries/render-utils/src/Haze.slf @@ -0,0 +1,143 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Created by Nissim Hadar on 9/5/2107. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include DeferredTransform.slh@> +<$declareDeferredFrameTransform()$> + +<@include model/Light.slh@> + +<@include LightingModel.slh@> +<$declareLightBuffer()$> + +<@include LightDirectional.slh@> +<$declareLightingDirectional(_SCRIBE_NULL)$> + +<@include Haze.slh@> + +uniform sampler2D colorMap; + +vec4 unpackPositionFromZeye(vec2 texcoord) { + float Zeye = -texture(linearDepthMap, texcoord).x; + int side = 0; + if (isStereo()) { + if (texcoord.x > 0.5) { + texcoord.x -= 0.5; + side = 1; + } + texcoord.x *= 2.0; + } + return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); +} + +in vec2 varTexCoord0; +out vec4 outFragColor; + +void main(void) { + if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) != HAZE_MODE_IS_ACTIVE) { + discard; + } + + // Distance to fragment + vec4 eyeFragPos = unpackPositionFromZeye(varTexCoord0); + float distance = length(eyeFragPos.xyz); + + vec4 fragColor = texture(colorMap, varTexCoord0); + vec4 hazeColor = vec4(hazeParams.hazeColor, 1.0); + + // Directional light component is a function of the angle from the eye, between the fragment and the sun + DeferredFrameTransform deferredTransform = getDeferredFrameTransform(); + vec4 worldFragPos = getViewInverse() * eyeFragPos; + vec3 eyeFragDir = normalize(worldFragPos.xyz); + + Light light = getLight(); + //vec3 lightDirection = getLightDirection(light); + vec3 lightDirection = normalize(vec3(-1.0, -1.0, -1.0)); + + float directionalLightComponent = max(0.0, dot(eyeFragDir, -lightDirection)); + float power = min(1.0, pow(directionalLightComponent, hazeParams.directionalLightBlend)); + + vec4 directionalLightColor = vec4(hazeParams.directionalLightColor, 1.0); + + vec4 blendedHazeColor = + mix(hazeColor, directionalLightColor, power); + + vec4 potentialFragColor; + + if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) { + // Compute separately for reach colour + // Haze is based on both range and altitude + // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt + + // The eyepoint position is in the last column of the matrix + vec3 worldEyePos = getViewInverse()[3].xyz; + + // Note that the haze base reference affects only the haze density as function of altitude + vec3 hazeDensityDistribution = + hazeParams.colorModulationFactor * + exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + + vec3 hazeIntegral = hazeDensityDistribution * distance; + + const float slopeThreshold = 0.01; + float deltaHeight = worldFragPos.y - worldEyePos.y; + if (abs(deltaHeight) > slopeThreshold) { + float t = hazeParams.hazeAltitudeFactor * deltaHeight; + hazeIntegral *= (1.0 - exp (-t)) / t; + } + + vec3 hazeAmount = 1.0 - exp(-hazeIntegral); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, vec4(1.0, 1.0, 1.0, 1.0), vec4(hazeAmount, 1.0)); + } + else if ((hazeParams.hazeMode & HAZE_MODE_IS_ALTITUDE_BASED) != HAZE_MODE_IS_ALTITUDE_BASED) { + // Haze is based only on range + float hazeAmount = 1.0 - exp(-distance * hazeParams.hazeRangeFactor); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); + } + else { + // Haze is based on both range and altitude + // Taken from www.crytek.com/download/GDC2007_RealtimeAtmoFxInGamesRev.ppt + + // The eyepoint position is in the last column of the matrix + vec3 worldEyePos = getViewInverse()[3].xyz; + + // Note that the haze base reference affects only the haze density as function of altitude + float hazeDensityDistribution = + hazeParams.hazeRangeFactor * + exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference)); + + float hazeIntegral = hazeDensityDistribution * distance; + + const float slopeThreshold = 0.01; + float deltaHeight = worldFragPos.y - worldEyePos.y; + if (abs(deltaHeight) > slopeThreshold) { + float t = hazeParams.hazeAltitudeFactor * deltaHeight; + hazeIntegral *= (1.0 - exp (-t)) / t; + } + + float hazeAmount = 1.0 - exp(-hazeIntegral); + + // Compute color after haze effect + potentialFragColor = mix(fragColor, blendedHazeColor, hazeAmount); + } + + // Mix with background at far range + if (distance > 32000.0) { + outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue); + } + else { + outFragColor = potentialFragColor; + } +} + diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh new file mode 100644 index 0000000000..624a859de7 --- /dev/null +++ b/libraries/render-utils/src/Haze.slh @@ -0,0 +1,44 @@ + +<@if not HAZE_SLH@> +<@def HAZE_SLH@> + +const int HAZE_MODE_IS_ACTIVE = 1 << 0; +const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1; +const int HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED = 1 << 2; +const int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3; + +struct HazeParams { + vec3 hazeColor; + float directionalLightBlend; + + vec3 directionalLightColor; + float hazeBaseReference; + + vec3 colorModulationFactor; + int hazeMode; + + float hazeRangeFactor; + float hazeAltitudeFactor; + + float hazeRangeFactorKeyLight; + float hazeAltitudeFactorKeyLight; + + float backgroundBlendValue; +}; + +layout(std140) uniform hazeBuffer { + HazeParams hazeParams; +}; + +uniform sampler2D linearDepthMap; + +<@endif@> + diff --git a/libraries/render-utils/src/HazeStage.cpp b/libraries/render-utils/src/HazeStage.cpp index a72c9d7254..712111f3b3 100644 --- a/libraries/render-utils/src/HazeStage.cpp +++ b/libraries/render-utils/src/HazeStage.cpp @@ -26,7 +26,6 @@ HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const { } HazeStage::Index HazeStage::addHaze(const HazePointer& haze) { - auto found = _hazeMap.find(haze); if (found == _hazeMap.end()) { auto hazeId = _hazes.newElement(haze); @@ -61,3 +60,13 @@ void HazeStageSetup::run(const render::RenderContextPointer& renderContext) { } } +void FetchHazeStage::run(const render::RenderContextPointer& renderContext, model::HazePointer& haze) { + + auto hazeStage = renderContext->_scene->getStage(); + assert(hazeStage); + + if (hazeStage->_currentFrame._hazes.size()) { + auto hazeId = hazeStage->_currentFrame._hazes.front(); + haze = hazeStage->getHaze(hazeId); + } +} diff --git a/libraries/render-utils/src/HazeStage.h b/libraries/render-utils/src/HazeStage.h index 15b65d9ab7..34f2e8b400 100644 --- a/libraries/render-utils/src/HazeStage.h +++ b/libraries/render-utils/src/HazeStage.h @@ -17,7 +17,9 @@ #include #include -#include "LightingModel.h" +#include +#include +#include "model/Haze.h" // Haze stage to set up haze-related rendering tasks class HazeStage : public render::Stage { @@ -35,7 +37,6 @@ public: using HazeIndices = std::vector; - Index findHaze(const HazePointer& haze) const; Index addHaze(const HazePointer& haze); @@ -79,4 +80,13 @@ public: protected: }; +class FetchHazeStage { +public: + using JobModel = render::Job::ModelO; + + void run(const render::RenderContextPointer& renderContext, model::HazePointer& haze); + +private: + gpu::PipelinePointer _hazePipeline; +}; #endif diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c67a1c7875..d8b030bb4e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -40,6 +40,7 @@ #include "AntialiasingEffect.h" #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" +#include "DrawHaze.h" #include "OutlineEffect.h" #include @@ -57,6 +58,7 @@ void RenderDeferredTask::configure(const Config& config) { } +#pragma optimize("", off); void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { const auto& items = input.get(); auto fadeEffect = DependencyManager::get(); @@ -145,8 +147,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Create the cluster grid of lights, cpu job for now const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget).asVarying(); const auto lightClusters = task.addJob("LightClustering", lightClusteringPassInputs); - - + + // Add haze model + const auto hazeModel = task.addJob("FetchHazeStage"); + // DeferredBuffer is complete, now let's shade it into the LightingBuffer const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters).asVarying(); @@ -165,7 +169,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying(); task.addJob("DebugLightClusters", debugLightClustersInputs); } - + + const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeModel, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingFramebuffer)); + task.addJob("DrawHaze", drawHazeInputs); + const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Lighting Buffer ready for tone mapping diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index d8a2f44042..d609dd2300 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -51,7 +51,7 @@ void main(void) { frag.scattering, midNormalCurvature, lowNormalCurvature); - _fragColor = vec4(color, 1.0); + _fragColor = vec4(color, 1.0); } }