Browse Source

colorPicker/swatch srgb display.
dependency from @rextimmy: tolinear and togamma for color+lumnance.

Azaezel 8 years ago
parent
commit
d42b1a6be8

+ 44 - 6
Engine/source/core/color.h

@@ -34,6 +34,9 @@
 #include "console/engineAPI.h"
 #endif
 
+const F32 gGamma = 2.2f;
+const F32 gOneOverGamma = 1.f / 2.2f;
+
 class ColorI;
 
 
@@ -104,8 +107,10 @@ class ColorF
                                       (alpha >= 0.0f && alpha <= 1.0f); }
    void clamp();
 
-   ColorF toLinear() const;
-   ColorF toGamma() const;
+   ColorF toLinear();
+   ColorF toGamma();
+   //calculate luminance, make sure color is linear first
+   F32 luminance();
 
    static const ColorF ZERO;
    static const ColorF ONE;
@@ -209,6 +214,9 @@ class ColorI
 
    operator const U8*() const { return &red; }
 
+   ColorI toLinear();
+   ColorI toGamma();
+
    static const ColorI ZERO;
    static const ColorI ONE;
    static const ColorI WHITE;
@@ -465,14 +473,32 @@ inline void ColorF::clamp()
       alpha = 0.0f;
 }
 
-inline ColorF ColorF::toLinear() const
+inline ColorF ColorF::toGamma()
+{
+   ColorF color;
+   color.red = mPow(red,gOneOverGamma);
+   color.green = mPow(green, gOneOverGamma);
+   color.blue = mPow(blue, gOneOverGamma);
+   color.alpha = alpha;
+   return color;
+}
+
+inline ColorF ColorF::toLinear()
 {
-   return ColorF(mPow(red, 2.2f), mPow(green, 2.2f), mPow(blue, 2.2f), alpha);
+   ColorF color;
+   color.red = mPow(red,gGamma);
+   color.green = mPow(green, gGamma);
+   color.blue = mPow(blue, gGamma);
+   color.alpha = alpha;
+   return color;
 }
 
-inline ColorF ColorF::toGamma() const
+inline F32 ColorF::luminance()
 {
-   return ColorF(mPow(red, 1.0f / 2.2f), mPow(green, 1.0f / 2.2f), mPow(blue, 1.0f / 2.2f), alpha);
+   // ITU BT.709
+   //return red * 0.2126f + green * 0.7152f + blue * 0.0722f;
+   // ITU BT.601
+   return red * 0.3f + green * 0.59f + blue * 0.11f;
 }
 
 //------------------------------------------------------------------------------
@@ -945,6 +971,18 @@ inline String ColorI::getHex() const
 	return result;
 }
 
+inline ColorI ColorI::toGamma()
+{
+   ColorF color = (ColorF)*this;
+   return (ColorI)color.toGamma();
+}
+
+inline ColorI ColorI::toLinear()
+{
+   ColorF color = (ColorF)*this;
+   return (ColorI)color.toLinear();
+}
+
 //-------------------------------------- INLINE CONVERSION OPERATORS
 inline ColorF::operator ColorI() const
 {

+ 7 - 3
Engine/source/gui/buttons/guiSwatchButtonCtrl.cpp

@@ -58,7 +58,7 @@ ConsoleDocClass( GuiSwatchButtonCtrl,
 //-----------------------------------------------------------------------------
 
 GuiSwatchButtonCtrl::GuiSwatchButtonCtrl()
- : mSwatchColor( 1, 1, 1, 1 )
+   : mSwatchColor(1, 1, 1, 1), mUseSRGB(false)
 {
    mButtonText = StringTable->insert( "" );   
    setExtent(140, 30);
@@ -71,7 +71,8 @@ GuiSwatchButtonCtrl::GuiSwatchButtonCtrl()
 
 void GuiSwatchButtonCtrl::initPersistFields()
 {
-   addField( "color", TypeColorF, Offset( mSwatchColor, GuiSwatchButtonCtrl ), "The foreground color of GuiSwatchButtonCtrl" );
+   addField("color", TypeColorF, Offset(mSwatchColor, GuiSwatchButtonCtrl), "The foreground color of GuiSwatchButtonCtrl");
+   addField( "useSRGB", TypeBool, Offset( mUseSRGB, GuiSwatchButtonCtrl ), "Render using sRGB scale" );
 
    addField( "gridBitmap", TypeString, Offset( mGridBitmap, GuiSwatchButtonCtrl ), "The bitmap used for the transparent grid" );
    
@@ -107,7 +108,10 @@ void GuiSwatchButtonCtrl::onRender( Point2I offset, const RectI &updateRect )
       drawer->drawBitmapStretch( mGrid, renderRect );
 
    // Draw swatch color as fill...
-   drawer->drawRectFill( renderRect, mSwatchColor );
+   if (!mUseSRGB)
+      drawer->drawRectFill( renderRect, mSwatchColor.toGamma() );
+   else
+      drawer->drawRectFill(renderRect, mSwatchColor);
 
    // Draw any borders...
    drawer->drawRect( renderRect, borderColor );

+ 1 - 1
Engine/source/gui/buttons/guiSwatchButtonCtrl.h

@@ -40,7 +40,7 @@ class GuiSwatchButtonCtrl : public GuiButtonBaseCtrl
       
       /// The color to display on the button.
       ColorF mSwatchColor;
-      
+      bool mUseSRGB;          ///< use sRGB color scale
       /// Bitmap used for mGrid
       String mGridBitmap;
 

+ 59 - 31
Engine/source/gui/controls/guiColorPicker.cpp

@@ -73,6 +73,7 @@ GuiColorPickerCtrl::GuiColorPickerCtrl()
    mSelectColor = false;
    mSetColor = mSetColor.BLACK;
    mBitmap = NULL;
+   mUseSRGB = false;
 }
 
 GuiColorPickerCtrl::~GuiColorPickerCtrl()
@@ -104,6 +105,7 @@ void GuiColorPickerCtrl::initPersistFields()
    addGroup("ColorPicker");
       addField("baseColor", TypeColorF, Offset(mBaseColor, GuiColorPickerCtrl));
       addField("pickColor", TypeColorF, Offset(mPickColor, GuiColorPickerCtrl));
+      addField("useSRGB", TypeBool, Offset(mUseSRGB, GuiColorPickerCtrl), "Render using sRGB scale");
       addField("selectorGap", TypeS32,  Offset(mSelectorGap, GuiColorPickerCtrl)); 
       addField("displayMode", TYPEID< PickMode >(), Offset(mDisplayMode, GuiColorPickerCtrl) );
       addField("actionOnMove", TypeBool,Offset(mActionOnMove, GuiColorPickerCtrl));
@@ -120,24 +122,35 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
 
    S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x;
    S32 t = bounds.point.y, b = bounds.point.y + bounds.extent.y;
-   
+
+   ColorF col[4];
+   col[0] = c1;
+   col[1] = c2;
+   col[2] = c3;
+   col[3] = c4;
+   if (!mUseSRGB)
+   {
+      for (U32 i = 0; i < 4; i++)
+         col[i] = col[i].toGamma();
+   }
+
    //A couple of checks to determine if color blend
    //A couple of checks to determine if color blend
-   if(c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
+   if (c1 == colorWhite && c3 == colorAlpha && c4 == colorBlack)
    {
       //Color
       PrimBuild::begin(GFXTriangleStrip, 4);
 
-      PrimBuild::color( c2 );
+      PrimBuild::color(col[1]);
       PrimBuild::vertex2i(l, t);
 
-      PrimBuild::color( c2 );
+      PrimBuild::color(col[1]);
       PrimBuild::vertex2i(r, t);
 
-      PrimBuild::color( c2 );
-      PrimBuild::vertex2i( l, b );
+      PrimBuild::color(col[1]);
+      PrimBuild::vertex2i(l, b);
 
-      PrimBuild::color( c2 );
+      PrimBuild::color(col[1]);
       PrimBuild::vertex2i(r, b);
 
       PrimBuild::end();
@@ -145,14 +158,14 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
       //White
       PrimBuild::begin(GFXTriangleStrip, 4);
 
-      PrimBuild::color(c1);
+      PrimBuild::color(col[0]);
       PrimBuild::vertex2i(l, t);
 
-      PrimBuild::color( colorAlphaW );
+      PrimBuild::color(colorAlphaW);
       PrimBuild::vertex2i(r, t);
 
-      PrimBuild::color( c1 );
-      PrimBuild::vertex2i( l, b );
+      PrimBuild::color(col[0]);
+      PrimBuild::vertex2i(l, b);
 
       PrimBuild::color(colorAlphaW);
       PrimBuild::vertex2i(r, b);
@@ -162,15 +175,15 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
       //Black 
       PrimBuild::begin(GFXTriangleStrip, 4);
 
-      PrimBuild::color(c3);
+      PrimBuild::color(col[2]);
       PrimBuild::vertex2i(l, t);
-      PrimBuild::color( c3 );
-      PrimBuild::vertex2i( r, t );
+      PrimBuild::color(col[2]);
+      PrimBuild::vertex2i(r, t);
 
-      PrimBuild::color( c4 );
+      PrimBuild::color(col[3]);
       PrimBuild::vertex2i(l, b);
 
-      PrimBuild::color( c4 );
+      PrimBuild::color(col[3]);
       PrimBuild::vertex2i(r, b);
 
       PrimBuild::end();
@@ -179,17 +192,17 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
    {
       PrimBuild::begin(GFXTriangleStrip, 4);
 
-      PrimBuild::color( c1 );
-      PrimBuild::vertex2i( l, t );
+      PrimBuild::color(col[0]);
+      PrimBuild::vertex2i(l, t);
 
-      PrimBuild::color( c2 );
-      PrimBuild::vertex2i( r, t );
+      PrimBuild::color(col[1]);
+      PrimBuild::vertex2i(r, t);
 
-      PrimBuild::color(c4);
+      PrimBuild::color(col[3]);
       PrimBuild::vertex2i(l, b);
 	  
-      PrimBuild::color( c3 );
-      PrimBuild::vertex2i( r, b );
+      PrimBuild::color(col[2]);
+      PrimBuild::vertex2i(r, b);
 
       PrimBuild::end();
    }
@@ -199,6 +212,7 @@ void GuiColorPickerCtrl::drawBlendBox(RectI &bounds, ColorF &c1, ColorF &c2, Col
 /// Function to draw a set of boxes blending throughout an array of colors
 void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numColors, ColorI *colors)
 {
+
    GFX->setStateBlock(mStateBlock);
 
    S32 l = bounds.point.x, r = bounds.point.x + bounds.extent.x + 4;
@@ -208,6 +222,20 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC
    S32 x_inc = int(mFloor((r - l) / F32(numColors - 1)));
    S32 y_inc = int(mFloor((b - t) / F32(numColors - 1)));
 
+   ColorI *col = new ColorI[numColors];
+   dMemcpy(col, colors, numColors * sizeof(ColorI));
+   if (mUseSRGB)
+   {
+      for (U16 i = 0; i < numColors - 1; i++)
+         col[i] = colors[i];
+   }
+   else
+   {
+      for (U16 i = 0; i < numColors - 1; i++)
+         col[i] = colors[i].toGamma();
+   }
+
+
    for (U16 i = 0; i < numColors - 1; i++)
    {
       // This is not efficent, but then again it doesn't really need to be. -pw
@@ -216,30 +244,30 @@ void GuiColorPickerCtrl::drawBlendRangeBox(RectI &bounds, bool vertical, U8 numC
       if (!vertical)  // Horizontal (+x)
       {
          // First color
-         PrimBuild::color(colors[i]);
+         PrimBuild::color(col[i]);
          PrimBuild::vertex2i(l, t);
-         PrimBuild::color(colors[i + 1]);
+         PrimBuild::color(col[i + 1]);
          PrimBuild::vertex2i(l + x_inc, t);
 
          // Second color
-         PrimBuild::color(colors[i]);
+         PrimBuild::color(col[i]);
          PrimBuild::vertex2i(l, b);
-         PrimBuild::color(colors[i + 1]);
+         PrimBuild::color(col[i + 1]);
          PrimBuild::vertex2i(l + x_inc, b);
          l += x_inc;
       }
       else  // Vertical (+y)
       {
          // First color
-         PrimBuild::color(colors[i]);
+         PrimBuild::color(col[i]);
          PrimBuild::vertex2i(l, t);
-         PrimBuild::color(colors[i + 1]);
+         PrimBuild::color(col[i + 1]);
          PrimBuild::vertex2i(l, t + y_inc);
 
          // Second color
-         PrimBuild::color(colors[i]);
+         PrimBuild::color(col[i]);
          PrimBuild::vertex2i(r, t);
-         PrimBuild::color(colors[i + 1]);
+         PrimBuild::color(col[i + 1]);
          PrimBuild::vertex2i(r, t + y_inc);
          t += y_inc;
       }

+ 1 - 0
Engine/source/gui/controls/guiColorPicker.h

@@ -90,6 +90,7 @@ class GuiColorPickerCtrl : public GuiControl
    ColorF mPickColor;		///< Color that has been picked from control
    ColorF mBaseColor;		///< Colour we display (in case of pallet and blend mode)
    PickMode mDisplayMode;	///< Current color display mode of the selector
+   bool mUseSRGB;          ///< use sRGB color scale
    
    Point2I mSelectorPos;	///< Current position of the selector
    bool mPositionChanged;	///< Current position has changed since last render?

+ 25 - 0
Templates/Empty/game/tools/gui/colorPicker.ed.gui

@@ -718,6 +718,22 @@
          canSave = "1";
          canSaveDynamicFields = "0";
       };
+      new GuiCheckBoxCtrl() {
+         text = "use sRGB";
+         groupNum = "-1";
+         buttonType = "ToggleButton";
+         useMouseEvents = "0";
+         position = "360 105";
+         extent = "66 16";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiCheckBoxProfile";
+         visible = "1";
+         active = "1";
+         variable = "$displayAsSRGB";
+		 command = "useSRGBctrl($displayAsSRGB);";
+      };
    };
 };
 //--- OBJECT WRITE END ---
@@ -727,6 +743,15 @@ $ColorPickerCancelCallback = "";
 $ColorPickerUpdateCallback = "";
 $ColorCallbackType   = 1;  // ColorI
 
+function useSRGBctrl(%colorScale)
+{
+ColorPickerDlg.useSRGB = %colorScale;
+ColorRangeSelect.useSRGB = %colorScale;
+ColorBlendSelect.useSRGB = %colorScale;
+myColor.useSRGB = %colorScale;
+oldColor.useSRGB = %colorScale;
+}
+
 // This function pushes the color picker dialog and returns to a callback the selected value
 function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback )
 {

+ 25 - 0
Templates/Full/game/tools/gui/colorPicker.ed.gui

@@ -718,6 +718,22 @@
          canSave = "1";
          canSaveDynamicFields = "0";
       };
+      new GuiCheckBoxCtrl() {
+         text = "use sRGB";
+         groupNum = "-1";
+         buttonType = "ToggleButton";
+         useMouseEvents = "0";
+         position = "360 105";
+         extent = "66 16";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiCheckBoxProfile";
+         visible = "1";
+         active = "1";
+         variable = "$displayAsSRGB";
+		 command = "useSRGBctrl($displayAsSRGB);";
+      };
    };
 };
 //--- OBJECT WRITE END ---
@@ -727,6 +743,15 @@ $ColorPickerCancelCallback = "";
 $ColorPickerUpdateCallback = "";
 $ColorCallbackType   = 1;  // ColorI
 
+function useSRGBctrl(%colorScale)
+{
+ColorPickerDlg.useSRGB = %colorScale;
+ColorRangeSelect.useSRGB = %colorScale;
+ColorBlendSelect.useSRGB = %colorScale;
+myColor.useSRGB = %colorScale;
+oldColor.useSRGB = %colorScale;
+}
+
 // This function pushes the color picker dialog and returns to a callback the selected value
 function GetColorI( %currentColor, %callback, %root, %updateCallback, %cancelCallback )
 {