From 74df83f376ddf1883fac07513e6e28c6902d2b95 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Fri, 27 Mar 2020 18:12:55 -0400
Subject: [PATCH] Revert "Revert "SL-12902 Fix for doing the technically
 correct but compatibility wrong thing WRT light color values.""

Fuck it. I hate everything even more. Really.

This reverts commit b5624e6db3ffcf6bb03ed539824081b1f3bfbbcb.
---
 indra/llmath/llmath.h           | 17 +++++++++++++----
 indra/llmath/v3color.h          |  9 +++++++++
 indra/llmath/v4color.h          | 11 +++++++++++
 indra/llprimitive/llprimitive.h | 14 ++++++++++----
 indra/newview/llvovolume.cpp    | 14 ++++----------
 indra/newview/llvovolume.h      | 17 ++++++++++++++---
 indra/newview/pipeline.cpp      | 13 ++++++++-----
 7 files changed, 69 insertions(+), 26 deletions(-)

diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 57f2489a2d6..8f01ad6c1ca 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -537,9 +537,12 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
 	}
 }
 
-// This converts from a non-linear sRGB floating point value (0..1) to a linear value.
-// Useful for gamma correction and such.  Note: any values passed through this should not be serialized.  You should also ideally cache the output of this.
-inline float sRGBtoLinear(const float val) {
+// Converts given value from a linear RGB floating point value (0..1) to a gamma corrected (sRGB) value.
+// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
+// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied
+// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch)
+// Note: DO NOT cache the conversion.  This leads to error prone synchronization and is actually slower in the typical case due to cache misses
+inline float linearTosRGB(const float val) {
     if (val < 0.0031308f) {
         return val * 12.92f;
     }
@@ -548,7 +551,13 @@ inline float sRGBtoLinear(const float val) {
     }
 }
 
-inline float linearTosRGB(const float val) {
+// Converts given value from a gamma corrected (sRGB) floating point value (0..1) to a linear color value.
+// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
+// Note: In our code, values labeled as sRGB are gamma corrected linear values, NOT linear values with monitor gamma applied
+// Note: Stored color values should generally be gamma corrected sRGB.  
+//       If you're serializing the return value of this function, you're probably doing it wrong.
+// Note: DO NOT cache the conversion.  This leads to error prone synchronization and is actually slower in the typical case due to cache misses.
+inline float sRGBtoLinear(const float val) {
     if (val < 0.04045f) {
         return val / 12.92f;
     }
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index ac78197510b..43a632408c7 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -484,4 +484,13 @@ inline const LLColor3 srgbColor3(const LLColor3 &a) {
 	return srgbColor;
 }
 
+inline const LLColor3 linearColor3(const LLColor3 &a) {
+    LLColor3 linearColor;
+    linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
+    linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
+    linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
+
+    return linearColor;
+}
+
 #endif
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 1b65d4a0035..c0e60e88fe6 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -659,6 +659,7 @@ void LLColor4::clamp()
 	}
 }
 
+// Return the given linear space color value in gamma corrected (sRGB) space
 inline const LLColor4 srgbColor4(const LLColor4 &a) {
     LLColor4 srgbColor;
 
@@ -670,5 +671,15 @@ inline const LLColor4 srgbColor4(const LLColor4 &a) {
     return srgbColor;
 }
 
+// Return the given gamma corrected (sRGB) color in linear space
+inline const LLColor4 linearColor4(const LLColor4 &a)
+{
+    LLColor4 linearColor;
+    linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
+    linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
+    linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
+    linearColor.mV[3] = a.mV[3];
+}
+
 #endif
 
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 20b5ad8eff9..ed89462e5a5 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -132,8 +132,7 @@ extern const F32 LIGHT_MAX_CUTOFF;
 class LLLightParams : public LLNetworkData
 {
 protected:
-	LLColor4 mColor; // alpha = intensity
-    LLColor4 mSRGBColor; // Only used in deferred (for now?)
+	LLColor4 mColor; // gamma corrected color (sRGB), alpha = intensity
 	F32 mRadius;
 	F32 mFalloff;
 	F32 mCutoff;
@@ -151,13 +150,20 @@ class LLLightParams : public LLNetworkData
 	bool fromLLSD(LLSD& sd);
 
 
-    void setColor(const LLColor4& color)	{ mColor = color; mColor.clamp(); mSRGBColor = srgbColor4(mColor); }
+    // set the color 
+    //  color - gamma corrected color value (directly taken from an on-screen color swatch)
+    void setColor(const LLColor4& color)	{ mColor = color; mColor.clamp(); }
 	void setRadius(F32 radius)				{ mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); }
 	void setFalloff(F32 falloff)			{ mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); }
 	void setCutoff(F32 cutoff)				{ mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); }
 
+    // same as getSRGBColor
     LLColor4 getColor() const				{ return mColor; }
-    LLColor4 getSRGBColor() const			{ return mSRGBColor; }
+    // get the sRGB (gamma corrected) color of this light
+    LLColor4 getSRGBColor() const			{ return mColor; }
+    // get the linear space color of this light
+    LLColor4 getLinearColor() const { return linearColor4(mColor); }
+
 	F32 getRadius() const					{ return mRadius; }
 	F32 getFalloff() const					{ return mFalloff; }
 	F32 getCutoff() const					{ return mCutoff; }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0acb623d2a2..aa42ca6a29e 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3279,17 +3279,11 @@ LLColor3 LLVOVolume::getLightBaseColor() const
 	}
 }
 
-LLColor3 LLVOVolume::getLightColor() const
+LLColor3 LLVOVolume::getLightLinearColor() const
 {
-	const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
-	if (param_block)
-	{
-		return LLColor3(param_block->getColor()) * param_block->getColor().mV[3];
-	}
-	else
-	{
-		return LLColor3(1,1,1);
-	}
+    LLColor3 ret = getLightSRGBColor();
+    ret = linearColor3(ret);
+    return ret;
 }
 
 LLColor3 LLVOVolume::getLightSRGBColor() const
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index f0458cf41b1..decc1952081 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -255,9 +255,20 @@ class LLVOVolume : public LLViewerObject
 	void setSpotLightParams(LLVector3 params);
 
 	BOOL getIsLight() const;
-	LLColor3 getLightBaseColor() const; // not scaled by intensity
-	LLColor3 getLightColor() const; // scaled by intensity
-    LLColor3 getLightSRGBColor() const; // Used to get the (cached) light color in sRGB color space.  Also scaled by intensity.
+
+
+    // Get the light color in sRGB color space NOT scaled by intensity.
+	LLColor3 getLightBaseColor() const; 
+    
+    //same as getLightSRGBColor()
+    LLColor3 getLightColor() const { return getLightSRGBColor(); }
+
+    // Same as linearColor3(getLightSRGBColor)
+    LLColor3 getLightLinearColor() const;
+
+    // Get the light color in sRGB color space scaled by intensity.
+    LLColor3 getLightSRGBColor() const; 
+
 	LLUUID	getLightTextureID() const;
 	bool isLightSpotlight() const;
 	LLVector3 getSpotLightParams() const;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 702dadfb9dd..b3ed7e95b21 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6369,7 +6369,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 				mLightMovingMask |= (1<<cur_light);
 			}
 			
-			LLColor4  light_color = sRenderDeferred ? light->getLightSRGBColor() : light->getLightColor();
+            //NOTE: for legacy reasons, send sRGB color to light shader for both deferred and non-deferred path
+			LLColor4  light_color = light->getLightColor();
 			light_color.mV[3] = 0.0f;
 
 			F32 fade = iter->fade;
@@ -8813,7 +8814,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
 					const F32* c = center.getF32ptr();
 					F32 s = volume->getLightRadius()*1.5f;
 
-                    LLColor3 col = volume->getLightSRGBColor();
+                    //NOTE: for legacy reasons, send sRGB color to light shader
+                    LLColor3 col = volume->getLightColor();
 					
 					if (col.magVecSquared() < 0.001f)
 					{
@@ -8905,7 +8907,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
 
 					setupSpotLight(gDeferredSpotLightProgram, drawablep);
 					
-                    LLColor3 col = volume->getLightSRGBColor();
+                    //NOTE: for legacy reasons, send sRGB color to light shader
+                    LLColor3 col = volume->getLightColor();
 					
 					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
 					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
@@ -8994,8 +8997,8 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
 					
 					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
 
-                    LLColor3 col = volume->getLightSRGBColor();
-					
+                    //NOTE: for legacy reasons, send sRGB color to light shader
+                    LLColor3 col = volume->getLightColor();
 					
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
                     gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final);
-- 
GitLab