?? Unity實作調色板
Unity Color官方檔案
Unity自帶的調色板是如何實作的?RGB和色彩空間中的HSV有什么關系?

RGB
RGB分別對應的是Red(紅)、Green(綠)、Blue(藍),又稱三原色光,通過對紅、綠、藍三個顏色通道(每個顏色通道都存放著影像中顏色元素的資訊)的變化以及它們相互之間的疊加來得到各式各樣的顏色的,即將這三種顏色在不同比例和強度上混合,可以得到其他各種顏色,
紅、綠、藍三個顏色通道每種色各分為256階亮度,0時最暗,255時最亮,所以三色灰度都為0時,是最暗的黑色調;三色灰度都為255時,是最亮的白色調,
世界上任何一種顏色的“顏色空間”都可定義成一個固定的數字或變數,RGB(紅、綠、藍)只是眾多顏色空間的一種,采用這種編碼方法,每種顏色都可用三個變數來表示-紅色綠色以及藍色的強度,
HSB(HSV)
RGB是對機器友好的編碼方式,想要知道色彩的明亮程度,有一種更友好的編碼方式就是HSB和HSL,
HSB還有另一種對等的說法即HSV,
HSB分別代表以下含義:
H(Hub):色相,在0~360°的標準色輪上,色相是按位置度量的,黑色和白色無色相,
S(Saturation):飽和度,表示色彩的純度,為0時為灰色,白、黑和其他灰色色彩都沒有飽和度的,在最大飽和度時,每一色相具有最純的色光,取值范圍0~100%,
B(Brightness/Value):亮度,為0時即為黑色,

調色板的實作
首先我們需要明確每一部分都指代的是什么,當顏色改變時,paint模塊會相應的獲取到顏色的值并改變;hue就是HSV中的H(色相);Saturation中的橫軸是HSV中的S(飽和度),縱軸是HSV中的V(亮度),

unity有RGB和HSV之間互相轉換的方法,我們可以直接使用,將模塊的HSV值轉換成RGB,或者是傳入一個默認的RGB色值,定位調色板中的具體位置,
private Color HSVToRGB(Vector4 hsv)
{
var color = Color.HSVToRGB(hsv.x, hsv.y, hsv.z);
color.a = hsv.w;
return color;
}
public void RGBToHSV(Color color)
{
Color.RGBToHSV(color, out currentColorHSV.x, out currentColorHSV.y, out currentColorHSV.z);
// 更新調色板的位置
}
Hue
我們需要通過hue模塊中滑塊的位置來轉換RGB色值
currentColorHSV是一個初始化為private Vector4 currentColorHSV = new Vector4(0, 1, 1, 1);的坐標,x代表hue的位置,y代表S,z代表V,w代表透明度,
private Color GetHue(float y)
{
var hueHSV = new Vector4(y, currentColorHSV.y, currentColorHSV.z, 1);
return HSVToRGB(hueHSV);
}
alpha
該模塊的處理方式和Hue模塊類似,只需要傳入alpha模塊中滑塊的位置即可
private Color GetAlpha(float y)
{
var hueHSV = new Vector4(currentColorHSV.x, currentColorHSV.y, currentColorHSV.z, y);
return HSVToRGB(hueHSV);
}
Saturation
該模塊內部包含了一個能夠滑動的圖示,我們需要給這個圖示規定能夠滑動的范圍limitBounds

limitBounds的值需要根據Saturation的大小來設定,由于此處的Saturation為一個邊長為256的正方形,所以設定的邊界值如下

然后我們需要獲取滑塊的位置,此處需要進行坐標的轉換
public Camera m_camera;
public RectTransform content;
public Vector3 contentPoint;
public Vector4 limitBounds;
public ScrollRect.ScrollRectEvent onValueChanged;
private RectTransform rect;
private Vector3 screenPoint;
public override void OnPointerDown(PointerEventData eventData)
{
screenPoint = m_camera.WorldToScreenPoint(transform.position);
var world = m_camera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, screenPoint.z));
contentPoint = rect.InverseTransformPoint(world);
contentPoint.x = Mathf.Max(limitBounds.x, Mathf.Min(limitBounds.y, contentPoint.x));
contentPoint.y = Mathf.Max(limitBounds.z, Mathf.Min(limitBounds.w, contentPoint.y));
content.anchoredPosition = contentPoint;
onValueChanged.Invoke(contentPoint);
}
public void OnDrag(PointerEventData eventData)
{
screenPoint = m_camera.WorldToScreenPoint(transform.position);
var world = m_camera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, screenPoint.z));
contentPoint = rect.InverseTransformPoint(world);
contentPoint.x = Mathf.Max(limitBounds.x, Mathf.Min(limitBounds.y, contentPoint.x));
contentPoint.y = Mathf.Max(limitBounds.z, Mathf.Min(limitBounds.w, contentPoint.y));
content.anchoredPosition = contentPoint;
onValueChanged.Invoke(contentPoint);
}
然后在colorpick組件中,我們需要獲取該點的位置,同時轉換成為RGB,更新即可,
// 根據Saturation中滑塊的位置,轉換成為HSV
private Vector2 GetSaturationHSV(Vector2 point)
{
var hsv = new Vector2();
hsv.x = point.x / saturation.rectTransform.sizeDelta.x + 0.5f;
hsv.y = point.y / saturation.rectTransform.sizeDelta.y + 0.5f;
return hsv;
}
// 根據HSV值得到滑塊的位置,相當于一個逆向操作
private Vector2 GetSaturationPoint(Vector4 hsv)
{
var point = new Vector2();
point.x = (hsv.y - 0.5f) * saturation.rectTransform.sizeDelta.x;
point.y = (hsv.z - 0.5f) * saturation.rectTransform.sizeDelta.y;
return point;
}
// 更新Saturation模塊中滑塊的位置
public void UpdateSaturationPoint(Vector4 hsv)
{
var saturationPoint = GetSaturationPoint(hsv);
scrollRectSaturation.content.anchoredPosition = saturationPoint;
}
最后,我們不要忘記加上對對滑塊值改變的監聽事件,
那么如果已知一個值,如何通過傳入的值將整個面板的滑塊進行重新定位呢?
只需要呼叫RGBToHSV函式即可,最后為什么要呼叫一遍OnHueClick的原因是該事件監聽的是Hue中滑塊的移動,即Hue滑塊值的改變,那么這個值在傳入RGB色值轉換成為HSV后不一定會改變,導致Saturation模塊不會進行重繪操作,所以可以直接呼叫一遍監聽事件,
public void RGBToHSV(Color color)
{
Color.RGBToHSV(color, out currentColorHSV.x, out currentColorHSV.y, out currentColorHSV.z);
scrollbarHue.value = https://www.cnblogs.com/wxiaonan/p/1 - currentColorHSV.x;
OnHueClick(scrollbarHue.value);
}
paint
只需要在HSV改變的時候將轉換后的RGB給paint模塊即可
private void PaintChange()
{
paint.color = HSVToRGB(currentColorHSV);;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/501139.html
標籤:其他
上一篇:HCIA學習筆記八:子網掩碼劃分
