Browse Source

Color blending fixes (#208)

* Fixed the animation color blending, and fixed an error in the gradient color lerp.

* Didn't mean to square the alpha.

* Moved the rounded lerp for Colourbs into its own function.

Co-authored-by: Jacqueline <[email protected]>
jac8888 4 years ago
parent
commit
8b6a361c0c

+ 7 - 0
Include/RmlUi/Core/Math.h

@@ -30,9 +30,13 @@
 #define RMLUI_CORE_MATH_H
 
 #include "Header.h"
+#include <type_traits>
 
 namespace Rml {
 
+using byte = unsigned char;
+template <typename ColourType, int AlphaDefault> class Colour;
+using Colourb = Colour< byte, 255 >;
 template <typename Type> class Vector2;
 using Vector2f = Vector2< float >;
 
@@ -74,9 +78,12 @@ Type Clamp(Type value, Type min, Type max)
 template< typename Type >
 Type Lerp(float t, Type v0, Type v1)
 {
+	static_assert(!std::is_same<Type, Colourb>::value, "Lerp currently cannot be used with Colourb. Use RoundedLerp instead.");
 	return v0 * (1.0f - t) + v1 * t;
 }
 
+Colourb RoundedLerp(float t, Colourb v0, Colourb v1);
+
 /// Evaluates if a number is, or close to, zero.
 /// @param[in] value The number to compare to zero.
 /// @return True if the number if zero or close to it, false otherwise.

+ 4 - 4
Source/Core/DecoratorGradient.cpp

@@ -95,16 +95,16 @@ DecoratorDataHandle DecoratorGradient::GenerateElementData(Element* element) con
 	{
 		for (int i = 0; i < (int)vertices.size(); i++)
 		{
-			const float t = (vertices[i].position.x - padding_offset.x) / padding_size.x;
-			vertices[i].colour = Math::Lerp(Math::Clamp(t, 0.0f, 1.0f), colour_start, colour_stop);
+			const float t = Math::Clamp((vertices[i].position.x - padding_offset.x) / padding_size.x, 0.0f, 1.0f);
+			vertices[i].colour = Math::RoundedLerp(t, colour_start, colour_stop);
 		}
 	}
 	else if (dir == Direction::Vertical)
 	{
 		for (int i = 0; i < (int)vertices.size(); i++)
 		{
-			const float t = (vertices[i].position.y - padding_offset.y) / padding_size.y;
-			vertices[i].colour = Math::Lerp(t, colour_start, colour_stop);
+			const float t = Math::Clamp((vertices[i].position.y - padding_offset.y) / padding_size.y, 0.0f, 1.0f);
+			vertices[i].colour = Math::RoundedLerp(t, colour_start, colour_stop);
 		}
 	}
 

+ 10 - 7
Source/Core/ElementAnimation.cpp

@@ -41,19 +41,22 @@ static Colourf ColourToLinearSpace(Colourb c)
 {
 	Colourf result;
 	// Approximate inverse sRGB function
-	result.red = Math::SquareRoot((float)c.red / 255.f);
-	result.green = Math::SquareRoot((float)c.green / 255.f);
-	result.blue = Math::SquareRoot((float)c.blue / 255.f);
-	result.alpha = (float)c.alpha / 255.f;
+	result.red = c.red / 255.f;
+	result.red *= result.red;
+	result.green = c.green / 255.f;
+	result.green *= result.green;
+	result.blue = c.blue / 255.f;
+	result.blue *= result.blue;
+	result.alpha = c.alpha / 255.f;
 	return result;
 }
 
 static Colourb ColourFromLinearSpace(Colourf c)
 {
 	Colourb result;
-	result.red = (byte)Math::Clamp(c.red*c.red*255.f, 0.0f, 255.f);
-	result.green = (byte)Math::Clamp(c.green*c.green*255.f, 0.0f, 255.f);
-	result.blue = (byte)Math::Clamp(c.blue*c.blue*255.f, 0.0f, 255.f);
+	result.red = (byte)Math::Clamp(Math::SquareRoot(c.red)*255.f, 0.0f, 255.f);
+	result.green = (byte)Math::Clamp(Math::SquareRoot(c.green)*255.f, 0.0f, 255.f);
+	result.blue = (byte)Math::Clamp(Math::SquareRoot(c.blue)*255.f, 0.0f, 255.f);
 	result.alpha = (byte)Math::Clamp(c.alpha*255.f, 0.0f, 255.f);
 	return result;
 }

+ 2 - 24
Source/Core/GeometryBackgroundBorder.cpp

@@ -258,22 +258,11 @@ void GeometryBackgroundBorder::DrawArc(Vector2f pos_center, Vector2f r, float a0
 		const float t = float(i) / float(num_points - 1);
 
 		const float a = Math::Lerp(t, a0, a1);
-		const Colourb color
-		{
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[0]), static_cast<float>(color1[0])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[1]), static_cast<float>(color1[1])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[2]), static_cast<float>(color1[2])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[3]), static_cast<float>(color1[3]))))
-		};
 
 		const Vector2f unit_vector(Math::Cos(a), Math::Sin(a));
 
 		vertices[offset_vertices + i].position = unit_vector * r + pos_center;
-		vertices[offset_vertices + i].colour = color;
+		vertices[offset_vertices + i].colour = Math::RoundedLerp(t, color0, color1);
 	}
 }
 
@@ -346,18 +335,7 @@ void GeometryBackgroundBorder::DrawArcArc(Vector2f pos_center, float R, Vector2f
 		const float t = float(i) / float(num_points - 1);
 
 		const float a = Math::Lerp(t, a0, a1);
-		const Colourb color
-		{
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[0]), static_cast<float>(color1[0])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[1]), static_cast<float>(color1[1])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[2]), static_cast<float>(color1[2])))),
-			static_cast<unsigned char>(Math::RoundToInteger(Math::Lerp(t, 
-				static_cast<float>(color0[3]), static_cast<float>(color1[3]))))
-		};
-
+		const Colourb color = Math::RoundedLerp(t, color0, color1);
 		const Vector2f unit_vector(Math::Cos(a), Math::Sin(a));
 
 		vertices[offset_vertices + 2 * i].position = unit_vector * r + pos_center;

+ 14 - 0
Source/Core/Math.cpp

@@ -248,5 +248,19 @@ RMLUICORE_API bool RandomBool()
 	return RandomInteger(2) == 1;
 }
 
+Colourb RoundedLerp(float t, Colourb v0, Colourb v1)
+{
+	return Colourb{
+		static_cast<unsigned char>(RoundToInteger(Lerp(t, 
+			static_cast<float>(v0[0]), static_cast<float>(v1[0])))),
+		static_cast<unsigned char>(RoundToInteger(Lerp(t, 
+			static_cast<float>(v0[1]), static_cast<float>(v1[1])))),
+		static_cast<unsigned char>(RoundToInteger(Lerp(t, 
+			static_cast<float>(v0[2]), static_cast<float>(v1[2])))),
+		static_cast<unsigned char>(RoundToInteger(Lerp(t, 
+			static_cast<float>(v0[3]), static_cast<float>(v1[3]))))
+	};
+}
+
 }
 } // namespace Rml