Unityで自由な色選択をしたい。
フリーのアセットもあるけど、ちょっとイメージと違った。
勉強もかねて自分で作ってみる。
GoogleだとHSV空間を使った選択ができた。
なんとなくRBG空間でやりたいのでこの方法はいったん置く。
まず色のRGB成分を8bit(0-255)の間でずらして設定するとこうなる。
これだとR, G, B 全ての値を持つ色(白:255,255,255とか)を表現できない。
そこで縦軸を使って白や黒も出るようにする。
これをスクリプトで書くとこうなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class ColorPicker : MonoBehaviour { GameObject canvas,picker; float c(float f){ return f<0 ? 0 : f>256 ? 1 : f/256f; } void Start () { canvas = GameObject.Find("Canvas"); //キャンバス picker = new GameObject("Picker"); //メイン部分 int w = 256*3-1,h=256; Texture2D tex = new Texture2D(w,h); float r,g,b,ex; for(int i=0;i<w;i++)for(int j=0;j<h;j++){ r = Mathf.Max(256-i,i-512,0); g = i<256 ? i : Mathf.Max(512-i,0); b = i<512 ? Mathf.Max(i-256,0) : 768-i; ex= j-h/2; tex.SetPixel(i,j,new Color(c(r+ex) , c(g+ex) , c(b+ex) , 1)); } tex.Apply(); // ピッカーの設定 picker.transform.parent = canvas.transform; Image img = picker.AddComponent<Image>(); picker.GetComponent<RectTransform>().anchoredPosition = Vector2.zero; picker.GetComponent<RectTransform>().sizeDelta = new Vector2(1024,1024); img.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero); } } |
キャンバスにでもアタッチすればこんな感じで表示される。
これだとR, G, Bが同値の色(灰色とか)を表現できないし、白や黒が複数存在する。
そもそも3次元の値なので2次元では表現しきれない。
円状のマップ
ピッカーを長方形から円にして90°, 210°, 330°方向をRGB軸にしてみる。
3軸あるようだけど直交していないので表現できない色がある。
中心からの距離で明るさを変えて、サイドバーで調整できるような感じにする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
int rad=256; Texture2D tex = new Texture2D(2*rad+1,2*rad+1);//メインテクスチャ float r,g,b,t; Vector2 vo, vr=new Vector2(0,1), vg=new Vector2(-0.866f,-0.5f), vb=new Vector2(0.866f,-0.5f); for(int i=0;i<=2*rad;i++)for(int j=0;j<=2*rad;j++){ if(isIn(i-rad,j-rad,rad)){ vo = new Vector2(i-rad,j-rad); r = 1f - Vector2.Angle(vo,vr)/120f; if(r<0)r=0; g = 1f - Vector2.Angle(vo,vg)/120f; if(g<0)g=0; b = 1f - Vector2.Angle(vo,vb)/120f; if(b<0)b=0; t = vo.magnitude/rad; r+=1f-t; g+=1f-t; b+=1f-t; tex.SetPixel(i,j,new Color(r,g,b,1)); }else{ tex.SetPixel(i,j,Color.clear); } } Texture2D tex2 = new Texture2D(1,256); //サイドバーテクスチャ for(int i=0;i<256;i++)tex2.SetPixel(0,i,new Color(i/255f,i/255f,i/255f)); |
画面ではこんな感じ。
見たことある感じになってきた。
中心からの距離補正が適当すぎるので彩度を増やすような計算にしたほうが良いかもしれない。
そもそもテクスチャを自作する必要はないので、この方式を使うなら正しいやつを拾ってきて使ってもいい。
今日はとりあえずここまで。