From 041c584e04c3db83ce13b07009e10376995b82ea Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Wed, 19 Jun 2024 13:59:24 -0700
Subject: [PATCH 1/2] add ambient light color

---
 .../src/RenderableZoneEntityItem.cpp          |  1 +
 .../src/AmbientLightPropertyGroup.cpp         | 19 ++++++
 .../entities/src/AmbientLightPropertyGroup.h  |  5 +-
 .../entities/src/EntityItemProperties.cpp     |  5 +-
 libraries/entities/src/EntityPropertyFlags.h  | 66 ++++++++++---------
 libraries/graphics/src/graphics/Light.cpp     | 20 ++++++
 libraries/graphics/src/graphics/Light.h       | 10 ++-
 libraries/graphics/src/graphics/Light.slh     | 28 +++++---
 libraries/graphics/src/graphics/skybox.slf    | 12 +---
 libraries/networking/src/udt/PacketHeaders.h  |  1 +
 libraries/render-utils/src/GlobalLight.slh    |  8 ---
 libraries/render-utils/src/LightAmbient.slh   | 11 ++--
 .../render-utils/src/zone_drawAmbient.slf     |  5 +-
 .../create/assets/data/createAppTooltips.json |  3 +
 .../html/js/entityProperties.js               |  6 ++
 15 files changed, 130 insertions(+), 70 deletions(-)

diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
index ce2dae8d28..52b27cf211 100644
--- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
@@ -309,6 +309,7 @@ void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer&
     ambientLight->setOrientation(_lastRotation);
 
     // Set the ambient light
+    ambientLight->setAmbientColor(ColorUtils::toVec3(_ambientLightProperties.getAmbientColor()));
     ambientLight->setAmbientIntensity(_ambientLightProperties.getAmbientIntensity());
 
     if (_ambientLightProperties.getAmbientURL().isEmpty()) {
diff --git a/libraries/entities/src/AmbientLightPropertyGroup.cpp b/libraries/entities/src/AmbientLightPropertyGroup.cpp
index c430688113..ebba47a044 100644
--- a/libraries/entities/src/AmbientLightPropertyGroup.cpp
+++ b/libraries/entities/src/AmbientLightPropertyGroup.cpp
@@ -20,6 +20,7 @@
 #include "EntityItemPropertiesMacros.h"
 
 const float AmbientLightPropertyGroup::DEFAULT_AMBIENT_LIGHT_INTENSITY = 0.5f;
+const glm::u8vec3 AmbientLightPropertyGroup::DEFAULT_COLOR = { 0, 0, 0 };
 
 void AmbientLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties,
     ScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags,
@@ -28,11 +29,13 @@ void AmbientLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& des
     auto nodeList = DependencyManager::get<NodeList>();
     COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, AmbientIntensity, ambientIntensity);
     COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, AmbientURL, ambientURL);
+    COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_COLOR, AmbientLight, ambientLight, AmbientColor, ambientColor);
 }
 
 void AmbientLightPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {
     COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientLight, ambientIntensity, float, setAmbientIntensity);
     COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientLight, ambientURL, QString, setAmbientURL);
+    COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(ambientLight, ambientColor, u8vec3Color, setAmbientColor);
     
     // legacy property support
     COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ambientLightAmbientIntensity, float, setAmbientIntensity, getAmbientIntensity);
@@ -41,11 +44,14 @@ void AmbientLightPropertyGroup::copyFromScriptValue(const ScriptValue& object, c
 void AmbientLightPropertyGroup::merge(const AmbientLightPropertyGroup& other) {
     COPY_PROPERTY_IF_CHANGED(ambientIntensity);
     COPY_PROPERTY_IF_CHANGED(ambientURL);
+    COPY_PROPERTY_IF_CHANGED(ambientColor);
 }
 
 void AmbientLightPropertyGroup::debugDump() const {
     qCDebug(entities) << "   AmbientLightPropertyGroup: ---------------------------------------------";
     qCDebug(entities) << "        ambientIntensity:" << getAmbientIntensity();
+    qCDebug(entities) << "        ambientURL:" << getAmbientURL();
+    qCDebug(entities) << "        ambientColor:" << getAmbientColor();
 }
 
 void AmbientLightPropertyGroup::listChangedProperties(QList<QString>& out) {
@@ -55,6 +61,9 @@ void AmbientLightPropertyGroup::listChangedProperties(QList<QString>& out) {
     if (ambientURLChanged()) {
         out << "ambientLight-ambientURL";
     }
+    if (ambientColorChanged()) {
+        out << "ambientLight-ambientColor";
+    }
 }
 
 bool AmbientLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
@@ -68,6 +77,7 @@ bool AmbientLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
     
     APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_INTENSITY, getAmbientIntensity());
     APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_URL, getAmbientURL());
+    APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_COLOR, getAmbientColor());
     
     return true;
 }
@@ -81,9 +91,11 @@ bool AmbientLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& proper
     
     READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_INTENSITY, float, setAmbientIntensity);
     READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_URL, QString, setAmbientURL);
+    READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_COLOR, u8vec3Color, setAmbientColor);
     
     DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_LIGHT_INTENSITY, AmbientIntensity);
     DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_LIGHT_URL, AmbientURL);
+    DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_AMBIENT_LIGHT_COLOR, AmbientColor);
     
     processedBytes += bytesRead;
 
@@ -95,6 +107,7 @@ bool AmbientLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& proper
 void AmbientLightPropertyGroup::markAllChanged() {
     _ambientIntensityChanged = true;
     _ambientURLChanged = true;
+    _ambientColorChanged = true;
 }
 
 EntityPropertyFlags AmbientLightPropertyGroup::getChangedProperties() const {
@@ -102,6 +115,7 @@ EntityPropertyFlags AmbientLightPropertyGroup::getChangedProperties() const {
  
     CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_INTENSITY, ambientIntensity);
     CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_URL, ambientURL);
+    CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_COLOR, ambientColor);
     
     return changedProperties;
 }
@@ -109,6 +123,7 @@ EntityPropertyFlags AmbientLightPropertyGroup::getChangedProperties() const {
 void AmbientLightPropertyGroup::getProperties(EntityItemProperties& properties) const {
     COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientLight, AmbientIntensity, getAmbientIntensity);
     COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientLight, AmbientURL, getAmbientURL);
+    COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(AmbientLight, AmbientColor, getAmbientColor);
 }
 
 bool AmbientLightPropertyGroup::setProperties(const EntityItemProperties& properties) {
@@ -116,6 +131,7 @@ bool AmbientLightPropertyGroup::setProperties(const EntityItemProperties& proper
 
     SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientLight, AmbientIntensity, ambientIntensity, setAmbientIntensity);
     SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientLight, AmbientURL, ambientURL, setAmbientURL);
+    SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(AmbientLight, AmbientColor, ambientColor, setAmbientColor);
 
     return somethingChanged;
 }
@@ -125,6 +141,7 @@ EntityPropertyFlags AmbientLightPropertyGroup::getEntityProperties(EncodeBitstre
 
     requestedProperties += PROP_AMBIENT_LIGHT_INTENSITY;
     requestedProperties += PROP_AMBIENT_LIGHT_URL;
+    requestedProperties += PROP_AMBIENT_LIGHT_COLOR;
 
     return requestedProperties;
 }
@@ -141,6 +158,7 @@ void AmbientLightPropertyGroup::appendSubclassData(OctreePacketData* packetData,
 
     APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_INTENSITY, getAmbientIntensity());
     APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_URL, getAmbientURL());
+    APPEND_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_COLOR, getAmbientColor());
 }
 
 int AmbientLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, 
@@ -153,6 +171,7 @@ int AmbientLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned c
     
     READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_INTENSITY, float, setAmbientIntensity);
     READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_URL, QString, setAmbientURL);
+    READ_ENTITY_PROPERTY(PROP_AMBIENT_LIGHT_COLOR, u8vec3Color, setAmbientColor);
 
     return bytesRead;
 }
diff --git a/libraries/entities/src/AmbientLightPropertyGroup.h b/libraries/entities/src/AmbientLightPropertyGroup.h
index 67597d1713..020af68b11 100644
--- a/libraries/entities/src/AmbientLightPropertyGroup.h
+++ b/libraries/entities/src/AmbientLightPropertyGroup.h
@@ -37,6 +37,8 @@ class ScriptValue;
  * @property {string} ambientURL="" - A cube map image that defines the color of the light coming from each direction. If 
  *     <code>""</code> then the entity's {@link Entities.Skybox|Skybox} <code>url</code> property value is used, unless that also is <code>""</code> in which 
  *     case the entity's <code>ambientLightMode</code> property is set to <code>"inherit"</code>.
+ * @property {Color} ambientColor=0,0,0 - Sets the color of the ambient light if <code>ambientURL</code> is <code>""</code>, otherwise modifies the
+ *     color of the cube map image.
  */
 class AmbientLightPropertyGroup : public PropertyGroup {
 public:
@@ -87,9 +89,10 @@ public:
                                                 bool& somethingChanged) override;
 
     static const float DEFAULT_AMBIENT_LIGHT_INTENSITY;
-
+    static const glm::u8vec3 DEFAULT_COLOR;
     DEFINE_PROPERTY(PROP_AMBIENT_LIGHT_INTENSITY, AmbientIntensity, ambientIntensity, float, DEFAULT_AMBIENT_LIGHT_INTENSITY);
     DEFINE_PROPERTY_REF(PROP_AMBIENT_LIGHT_URL, AmbientURL, ambientURL, QString, "");
+    DEFINE_PROPERTY_REF(PROP_AMBIENT_LIGHT_COLOR, AmbientColor, ambientColor, glm::u8vec3, DEFAULT_COLOR);
 };
 
 #endif // hifi_AmbientLightPropertyGroup_h
diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp
index 54d20301ae..f51d15b8b0 100644
--- a/libraries/entities/src/EntityItemProperties.cpp
+++ b/libraries/entities/src/EntityItemProperties.cpp
@@ -2967,8 +2967,9 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr
             ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(PROP_KEYLIGHT_SHADOW_MAX_DISTANCE, KeyLight, keyLight, ShadowMaxDistance, shadowMaxDistance, 1.0f, 250.0f);
         }
         { // Ambient light
-            ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, Intensity, intensity);
-            ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, URL, url);
+            ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, AmbientIntensity, ambientIntensity);
+            ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, AmbientURL, ambientURL);
+            ADD_GROUP_PROPERTY_TO_MAP(PROP_AMBIENT_LIGHT_COLOR, AmbientLight, ambientLight, AmbientColor, ambientColor);
         }
         { // Skybox
             ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h
index ae8928b68e..ff7c4134fa 100644
--- a/libraries/entities/src/EntityPropertyFlags.h
+++ b/libraries/entities/src/EntityPropertyFlags.h
@@ -173,6 +173,7 @@ enum EntityPropertyList {
     PROP_DERIVED_37,
     PROP_DERIVED_38,
     PROP_DERIVED_39,
+    PROP_DERIVED_40,
 
     PROP_AFTER_LAST_ITEM,
 
@@ -284,44 +285,45 @@ enum EntityPropertyList {
     // Ambient light
     PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_6,
     PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_7,
+    PROP_AMBIENT_LIGHT_COLOR = PROP_DERIVED_8,
     // Skybox
-    PROP_SKYBOX_COLOR = PROP_DERIVED_8,
-    PROP_SKYBOX_URL = PROP_DERIVED_9,
+    PROP_SKYBOX_COLOR = PROP_DERIVED_9,
+    PROP_SKYBOX_URL = PROP_DERIVED_10,
     // Haze
-    PROP_HAZE_RANGE = PROP_DERIVED_10,
-    PROP_HAZE_COLOR = PROP_DERIVED_11,
-    PROP_HAZE_GLARE_COLOR = PROP_DERIVED_12,
-    PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_13,
-    PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_14,
-    PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_15,
-    PROP_HAZE_CEILING = PROP_DERIVED_16,
-    PROP_HAZE_BASE_REF = PROP_DERIVED_17,
-    PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_18,
-    PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_19,
-    PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_20,
-    PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_21,
+    PROP_HAZE_RANGE = PROP_DERIVED_11,
+    PROP_HAZE_COLOR = PROP_DERIVED_12,
+    PROP_HAZE_GLARE_COLOR = PROP_DERIVED_13,
+    PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_14,
+    PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_15,
+    PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_16,
+    PROP_HAZE_CEILING = PROP_DERIVED_17,
+    PROP_HAZE_BASE_REF = PROP_DERIVED_18,
+    PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_19,
+    PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_20,
+    PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_21,
+    PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_22,
     // Bloom
-    PROP_BLOOM_INTENSITY = PROP_DERIVED_22,
-    PROP_BLOOM_THRESHOLD = PROP_DERIVED_23,
-    PROP_BLOOM_SIZE = PROP_DERIVED_24,
-    PROP_FLYING_ALLOWED = PROP_DERIVED_25,
-    PROP_GHOSTING_ALLOWED = PROP_DERIVED_26,
-    PROP_FILTER_URL = PROP_DERIVED_27,
-    PROP_KEY_LIGHT_MODE = PROP_DERIVED_28,
-    PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_29,
-    PROP_SKYBOX_MODE = PROP_DERIVED_30,
-    PROP_HAZE_MODE = PROP_DERIVED_31,
-    PROP_BLOOM_MODE = PROP_DERIVED_32,
+    PROP_BLOOM_INTENSITY = PROP_DERIVED_23,
+    PROP_BLOOM_THRESHOLD = PROP_DERIVED_24,
+    PROP_BLOOM_SIZE = PROP_DERIVED_25,
+    PROP_FLYING_ALLOWED = PROP_DERIVED_26,
+    PROP_GHOSTING_ALLOWED = PROP_DERIVED_27,
+    PROP_FILTER_URL = PROP_DERIVED_28,
+    PROP_KEY_LIGHT_MODE = PROP_DERIVED_29,
+    PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_30,
+    PROP_SKYBOX_MODE = PROP_DERIVED_31,
+    PROP_HAZE_MODE = PROP_DERIVED_32,
+    PROP_BLOOM_MODE = PROP_DERIVED_33,
     // Avatar priority
-    PROP_AVATAR_PRIORITY = PROP_DERIVED_33,
+    PROP_AVATAR_PRIORITY = PROP_DERIVED_34,
     // Screen-sharing
-    PROP_SCREENSHARE = PROP_DERIVED_34,
+    PROP_SCREENSHARE = PROP_DERIVED_35,
     // Audio
-    PROP_REVERB_ENABLED = PROP_DERIVED_35,
-    PROP_REVERB_TIME = PROP_DERIVED_36,
-    PROP_REVERB_WET_LEVEL = PROP_DERIVED_37,
-    PROP_LISTENER_ZONES = PROP_DERIVED_38,
-    PROP_LISTENER_ATTENUATION_COEFFICIENTS = PROP_DERIVED_39,
+    PROP_REVERB_ENABLED = PROP_DERIVED_36,
+    PROP_REVERB_TIME = PROP_DERIVED_37,
+    PROP_REVERB_WET_LEVEL = PROP_DERIVED_38,
+    PROP_LISTENER_ZONES = PROP_DERIVED_39,
+    PROP_LISTENER_ATTENUATION_COEFFICIENTS = PROP_DERIVED_40,
 
     // Polyvox
     PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0,
diff --git a/libraries/graphics/src/graphics/Light.cpp b/libraries/graphics/src/graphics/Light.cpp
index fb14783b4e..abdfd52617 100644
--- a/libraries/graphics/src/graphics/Light.cpp
+++ b/libraries/graphics/src/graphics/Light.cpp
@@ -4,6 +4,7 @@
 //
 //  Created by Sam Gateau on 1/26/2014.
 //  Copyright 2014 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -156,6 +157,10 @@ void Light::setSpotExponent(float exponent) {
     _lightSchemaBuffer.edit().irradiance.falloffSpot = exponent;
 }
 
+void Light::setAmbientColor(vec3 color) {
+    _ambientSchemaBuffer.edit().color = color;
+}
+
 void Light::setAmbientIntensity(float intensity) {
     _ambientSchemaBuffer.edit().intensity = intensity;
 }
@@ -187,3 +192,18 @@ void Light::setTransform(const glm::mat4& transform) {
     }
 }
 
+const Light::AmbientSchemaBuffer& Light::getAmbientSchemaBuffer() {
+    auto blend = 0.0f;
+    if (getAmbientMap() && getAmbientMap()->isDefined()) {
+        blend = 0.5f;
+
+        // If pitch black neutralize the color
+        if (glm::all(glm::equal(getAmbientColor(), glm::vec3(0.0f)))) {
+            blend = 1.0f;
+        }
+    }
+
+    _ambientSchemaBuffer.edit().blend = blend;
+
+    return _ambientSchemaBuffer;
+}
diff --git a/libraries/graphics/src/graphics/Light.h b/libraries/graphics/src/graphics/Light.h
index 81a6fddbd3..cb09e17786 100644
--- a/libraries/graphics/src/graphics/Light.h
+++ b/libraries/graphics/src/graphics/Light.h
@@ -4,6 +4,7 @@
 //
 //  Created by Sam Gateau on 12/10/2014.
 //  Copyright 2014 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -143,7 +144,9 @@ public:
     void setSpotExponent(float exponent);
     float getSpotExponent() const { return _lightSchemaBuffer->irradiance.falloffSpot; }
 
-    // If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting
+    // If the light has an ambient (Indirect) component, then the AmbientColor and AmbientIntensity can be used to control its contribution to the lighting
+    void setAmbientColor(vec3 color);
+    vec3 getAmbientColor() const { return _ambientSchemaBuffer->color; }
     void setAmbientIntensity(float intensity);
     float getAmbientIntensity() const { return _ambientSchemaBuffer->intensity; }
 
@@ -169,6 +172,9 @@ public:
 
     class AmbientSchema {
     public:
+        vec3 color { 0.0f };
+        float blend { 0.0f };
+
         float intensity { 0.0f };
         float mapNumMips { 0.0f };
         float spare1;
@@ -182,7 +188,7 @@ public:
     using AmbientSchemaBuffer = gpu::StructBuffer<AmbientSchema>;
 
     const LightSchemaBuffer& getLightSchemaBuffer() const { return _lightSchemaBuffer; }
-    const AmbientSchemaBuffer& getAmbientSchemaBuffer() const { return _ambientSchemaBuffer; }
+    const AmbientSchemaBuffer& getAmbientSchemaBuffer(); // This also updates the blend factor to make sure it's current
 
 protected:
 
diff --git a/libraries/graphics/src/graphics/Light.slh b/libraries/graphics/src/graphics/Light.slh
index c00bfea6a2..d8ce697b98 100644
--- a/libraries/graphics/src/graphics/Light.slh
+++ b/libraries/graphics/src/graphics/Light.slh
@@ -4,6 +4,7 @@
 //
 //  Created by Sam Gateau on 1/25/14.
 //  Copyright 2013 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -15,7 +16,16 @@
 <@include graphics/LightVolume.shared.slh@>
 <@include graphics/LightIrradiance.shared.slh@>
 
-// NOw lets define Light
+// FIXME: For legacy reasons, when blend is 0.5, this is equivalent to:
+// color * texel
+// It should actually be:
+// mix(color, texel, blend)
+// and the blend factor should be user controlled
+vec3 applySkyboxColorMix(vec3 texel, vec3 color, float blend) {
+    return mix(vec3(1.0), texel, float(blend > 0.0)) * mix(vec3(1.0), color, float(blend < 1.0));
+}
+
+// Now let's define Light
 struct Light {
     LightVolume volume;
     LightIrradiance irradiance;
@@ -35,17 +45,19 @@ vec3 getLightIrradiance(Light l) { return lightIrradiance_getIrradiance(l.irradi
 // Light Ambient
 
 struct LightAmbient {
-    vec4 _ambient;
+    vec4 _ambientColor;
+    vec4 _ambientInfo;
     SphericalHarmonics _ambientSphere;
     mat4 transform;
 };
 
 SphericalHarmonics getLightAmbientSphere(LightAmbient l) { return l._ambientSphere; }
 
-
-float getLightAmbientIntensity(LightAmbient l) { return l._ambient.x; }
-bool getLightHasAmbientMap(LightAmbient l) { return l._ambient.y > 0.0; }
-float getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }
+vec3 getLightAmbientColor(LightAmbient l) { return l._ambientColor.xyz; }
+float getLightAmbientBlend(LightAmbient l) { return l._ambientColor.w; }
+float getLightAmbientIntensity(LightAmbient l) { return l._ambientInfo.x; }
+bool getLightHasAmbientMap(LightAmbient l) { return l._ambientInfo.y > 0.0; }
+float getLightAmbientMapNumMips(LightAmbient l) { return l._ambientInfo.y; }
 
 <@func declareLightBuffer(N)@>
 
@@ -71,10 +83,6 @@ Light getKeyLight() {
 <@endfunc@>
 
 
-
-
-
-
 <@func declareLightAmbientBuffer(N)@>
 
 <@if N@>
diff --git a/libraries/graphics/src/graphics/skybox.slf b/libraries/graphics/src/graphics/skybox.slf
index 4ae53a657f..2d5ba4d26b 100755
--- a/libraries/graphics/src/graphics/skybox.slf
+++ b/libraries/graphics/src/graphics/skybox.slf
@@ -5,17 +5,18 @@
 //
 //  Created by Sam Gateau on 5/5/2015.
 //  Copyright 2015 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
 //
 <@include graphics/ShaderConstants.h@>
 
+<@include graphics/Light.slh@>
 <@if HIFI_USE_FORWARD@>
     <@include gpu/Transform.slh@>
     <$declareStandardCameraTransform()$>
 
-    <@include graphics/Light.slh@>
     <$declareLightBuffer()$>
 
     <@include graphics/Haze.slh@>
@@ -35,17 +36,10 @@ layout(location=0) in vec3  _normal;
 layout(location=0) out vec4 _fragColor;
 
 void main(void) {
-    // FIXME: For legacy reasons, when skybox.color.a is 0.5, this is equivalent to:
-    // skyboxColor * skyboxTexel
-    // It should actually be:
-    // mix(skyboxColor, skyboxTexel, skybox.color.a)
-    // and the blend factor should be user controlled
-
     vec3 normal = normalize(_normal);
     vec3 skyboxTexel = texture(cubeMap, normal).rgb;
     vec3 skyboxColor = skybox.color.rgb;
-    _fragColor = vec4(mix(vec3(1.0), skyboxTexel, float(skybox.color.a > 0.0)) *
-                      mix(vec3(1.0), skyboxColor, float(skybox.color.a < 1.0)), 1.0);
+    _fragColor = vec4(applySkyboxColorMix(skyboxTexel, skyboxColor, skybox.color.a), 1.0);
 
 <@if HIFI_USE_FORWARD@>
     // FIXME: either move this elsewhere or give it access to isHazeEnabled() (which is in render-utils/LightingModel.slh)
diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h
index b4fb5a172d..3ea6abb078 100644
--- a/libraries/networking/src/udt/PacketHeaders.h
+++ b/libraries/networking/src/udt/PacketHeaders.h
@@ -296,6 +296,7 @@ enum class EntityVersion : PacketVersion {
     AudioZones,
     AnimationSmoothFrames,
     ProceduralParticles,
+    AmbientColor,
 
     // Add new versions above here
     NUM_PACKET_TYPE,
diff --git a/libraries/render-utils/src/GlobalLight.slh b/libraries/render-utils/src/GlobalLight.slh
index de8702ea8c..0593abe375 100644
--- a/libraries/render-utils/src/GlobalLight.slh
+++ b/libraries/render-utils/src/GlobalLight.slh
@@ -44,14 +44,6 @@
 
 <@endfunc@>
 
-<@func declareEvalAmbientGlobalColor()@>
-vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, float roughness) {
-    <$prepareGlobalLight(position, normal)$>
-    color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(lightAmbient);
-    return color;
-}
-<@endfunc@>
-
 <@func declareEvalAmbientSphereGlobalColor(supportScattering)@>
 
 <$declareLightingAmbient(1, _SCRIBE_NULL, _SCRIBE_NULL, $supportScattering$)$>
diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh
index cb76a8e545..81c672292a 100644
--- a/libraries/render-utils/src/LightAmbient.slh
+++ b/libraries/render-utils/src/LightAmbient.slh
@@ -2,6 +2,7 @@
 //
 //  Created by Sam Gateau on 7/5/16.
 //  Copyright 2016 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -74,7 +75,7 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface, ve
     }
     <@endif@>
 
-    return specularLight;
+    return applySkyboxColorMix(specularLight, getLightAmbientColor(ambient), getLightAmbientBlend(ambient));
 }
 <@endfunc@>
 
@@ -104,8 +105,9 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
 
     vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, surface.roughness);
 
-    diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * 
-              sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz;
+    diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) *
+              applySkyboxColorMix(sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceSurfaceNormal).xyz,
+                                  getLightAmbientColor(ambient), getLightAmbientBlend(ambient));
 
     // Specular highlight from ambient
     vec3 ambientSpaceLightDir = -reflect(ambientSpaceSurfaceEyeDir, ambientSpaceSurfaceNormal);
@@ -120,7 +122,8 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
         obscurance = min(obscurance, ambientOcclusion);
 
         // Diffuse from ambient
-        diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;
+        diffuse = applySkyboxColorMix(sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz,
+                                      getLightAmbientColor(ambient), getLightAmbientBlend(ambient));
 
         // Scattering ambient specular is the same as non scattering for now
         // TODO: we should use the same specular answer as for direct lighting
diff --git a/libraries/render-utils/src/zone_drawAmbient.slf b/libraries/render-utils/src/zone_drawAmbient.slf
index d780fd0de2..07eab08a35 100644
--- a/libraries/render-utils/src/zone_drawAmbient.slf
+++ b/libraries/render-utils/src/zone_drawAmbient.slf
@@ -4,6 +4,7 @@
 //
 //  Created by Sam Gateau on 5/16/17.
 //  Copyright 2017 High Fidelity, Inc.
+//  Copyright 2024 Overte e.V.
 //
 //  Distributed under the Apache License, Version 2.0.
 //  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@@ -41,10 +42,10 @@ void main(void) {
     vec3 ambientMap = evalSkyboxLight(fragNormal, lod).xyz;
     vec3 ambientSH = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(lightAmbient), fragNormal).xyz;
 
-   // vec3 ambient = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(lightAmbient), fragNormal).xyz;
-  //  _fragColor = vec4( 0.5  * (fragNormal + vec3(1.0)), 1.0);
+    // _fragColor = vec4( 0.5  * (fragNormal + vec3(1.0)), 1.0);
 
     vec3 color = mix(ambientSH, ambientMap, float(sphereUV.x > 0.0));
+    color = applySkyboxColorMix(color, getLightAmbientColor(lightAmbient), getLightAmbientBlend(lightAmbient));
 
     color = color * 1.0 - base.w + base.xyz * base.w;
     const float INV_GAMMA_22 = 1.0 / 2.2;
diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json
index 076f47f5dd..c4503763a3 100644
--- a/scripts/system/create/assets/data/createAppTooltips.json
+++ b/scripts/system/create/assets/data/createAppTooltips.json
@@ -116,6 +116,9 @@
     "ambientLight.ambientURL": {
         "tooltip": "A cube map image that defines the color of the light coming from each direction."
     },
+    "ambientLight.ambientColor": {
+        "tooltip": "If the URL is blank, this changes the color of the ambient light, otherwise it modifies the color of the ambient map."
+    },
     "hazeMode": {
         "tooltip": "Configures the haze in the scene."
     },
diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js
index 1eade2703d..5a1df0feee 100644
--- a/scripts/system/create/entityProperties/html/js/entityProperties.js
+++ b/scripts/system/create/entityProperties/html/js/entityProperties.js
@@ -449,6 +449,12 @@ const GROUPS = [
                 options: { inherit: "Inherit", disabled: "Off", enabled: "On" },
                 propertyID: "ambientLightMode",
             },
+            {
+                label: "Ambient Color",
+                type: "color",
+                propertyID: "ambientLight.ambientColor",
+                showPropertyRule: { "ambientLightMode": "enabled" },
+            },
             {
                 label: "Ambient Intensity",
                 type: "number-draggable",

From 0d0a0a7a157a7313ab033a54719222e60a217399 Mon Sep 17 00:00:00 2001
From: HifiExperiments <thingsandstuffblog@gmail.com>
Date: Fri, 21 Jun 2024 13:07:43 -0700
Subject: [PATCH 2/2] fix create issue

---
 libraries/entities/src/AmbientLightPropertyGroup.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/entities/src/AmbientLightPropertyGroup.cpp b/libraries/entities/src/AmbientLightPropertyGroup.cpp
index ebba47a044..ba03b8d2da 100644
--- a/libraries/entities/src/AmbientLightPropertyGroup.cpp
+++ b/libraries/entities/src/AmbientLightPropertyGroup.cpp
@@ -29,7 +29,7 @@ void AmbientLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& des
     auto nodeList = DependencyManager::get<NodeList>();
     COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_INTENSITY, AmbientLight, ambientLight, AmbientIntensity, ambientIntensity);
     COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_IF_URL_PERMISSION(PROP_AMBIENT_LIGHT_URL, AmbientLight, ambientLight, AmbientURL, ambientURL);
-    COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_AMBIENT_LIGHT_COLOR, AmbientLight, ambientLight, AmbientColor, ambientColor);
+    COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_AMBIENT_LIGHT_COLOR, AmbientLight, ambientLight, AmbientColor, ambientColor, u8vec3Color);
 }
 
 void AmbientLightPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) {