Making a Colour Picker

I am making the elements of the colour picker as vertex coloured procedural meshes. : Vertex colours not blending across triangle face - Questions & Answers - Unity Discussions

But now after searching, there doesn’t seem to be a way of reading the colour of a pixel at the mouse position on the screen, just how to read the colour from a pixel in a texture.

Is there a way to get the colour on the screen at the mouse position? The only way I can see to go forward now is to generate a 2D texture with what the camera can see, and go from there, but I really don’t want to do that (generating a new texture every time the main colour wheel gets changed)

I think, you can use Physics.Raycast to detect mouse click on the object and use hitpoint to get a texture color…

My problem is currently there is no texture, just a material with a vertex colour shader. The colours are set on the vertices of the mesh. To use GetColor I would have to generate a texture. Is it possible to read the colour of a pixel on the screen?

I’m quite curious about this as well. I assume you’re talking about using RaycastHit.textureCoord to do a GetPixels on the base texture? Would GetPixels return a valid color result if his vertex colored mesh didn’t actually have a texture?

All I could think of were render textures or Lerping between the vert color values for the triangle referenced using the RaycastHit.triangleIndex but didn’t think I knew enough about the required calculation to offer any solid advice.

Do it in maths
You can use EditorGUIUtility.HSVToRGB to get hsv into rgb during edit mode

See, now that’s handy!

I once had developed a photoshop-like colorpicker.
The rainbow on the left is a texture painted in Photoshop.
The squared field is a very accurate texture calculated on the fly with a nested for-loop.
Physics.Raycast to get the color:

1300939--60464--$Colorpicker.jpg

Maybe I can put it into the store.

Thank you everyone for responding.

Thank you hpjohn, your suggestion was very clever, that’s what I went with. I used a RGB ↔ HSV convertor here : Color Conversion Algorithms

Here is the result in action : http://www.alucardj.net16.net/unityquestions2013/ColourPicker.html

Now I just need to find out why the vertex colours on the vertices are not smoothly blending across the face of the triangle (link to that question is at the top of the post). Many thanks again =]

Pretty neat colour picker!

Thanks, I’m happy the result exceeded the concept too! I only just fixed the shader and vert winding on the quad, hope you saw that build. I’m still thinking adding more verts to the square to give the colours a smoother transition across the Quad.

I liked hpjohns answer so much I rewrote the colour assignment on the ring, so the whole thing is numbers (yay for math!), no texture or GetPixel used =]

Lookin good, but whats in the top right box doesn’t quite appear to be the same shade as selected in all cases, try a dark blue, middle of the box

I’m interested to know what the code behind this looks like .I’m not a very skilled programmer but I’m learning, would you be able to post a snippet of your code?

hpjohn : yes, I had a problem with the colours not blending evenly across a quad. When I changed it to a plane the colour blend seems a lot better.

Here is the new plane build : http://www.alucardj.net16.net/unityquestions2013/ColourPickerPlane.html

Using a Quad :

Using a plane :

this is the question I asked on UA about the vertex colours not being blended evenly across the face of the triangle : Vertex colours not blending across triangle face - Questions & Answers - Unity Discussions

hawx : I’m really not sure what you are interested in the most to give more detail.

The biggest part of this is the ‘Colour Calculator’, a helper script that converts colours between RGB and HSV values.

Once that was made, everything could work from the H value of the colour. The directional vector from the center of the ring to the pointer as an angle using Quaternion.FromToRotation. (please note all this script was just for testing, I positioned everything at zero and used screen center. In practice, these would be local positions relative to the objects).

function GetH() 
{
	if ( Input.GetMouseButtonDown(0) )
	{
		
	}
	else if ( Input.GetMouseButton(0) )
	{
		mousePos = Input.mousePosition;
		
		var halfWidth : float = Screen.width * 0.5;
		var halfHeight : float = Screen.height * 0.5;
		
		// get the directional vector of the mouse to the screen center
		//var dir : Vector3 = mousePos - Vector3( halfWidth, halfHeight, 0 );
		var dir : Vector3 = Vector3( mousePos.x, mousePos.y, 0 ) - Vector3( halfWidth, halfHeight, 0 ); // for inverting screen Y if needed
		
		// calculate a rotation for H based on the current mousePosition and up from the center of the screen
		var rot : Quaternion = Quaternion.FromToRotation( Vector3.up, dir.normalized );
		
		Debug.Log( rot.eulerAngles.z );
		//svPointer.renderer.material.color = colourCalc.HSVtoRGB( rot.eulerAngles.z, 1, 1 );
		
		// get a value for H betweeen 0 and 360
		hAngle = rot.eulerAngles.z; 
		
		// call function on shade object to change colour
		// convert and return a RGB colour from HSV values
		//hColour = colourCalc.HSVtoRGB( hAngle, 1, 1 ); // S = 1 (no white); V = 1 (no black);
		//colourPickerShade.SetColour( hColour ); // using colour
		// or just use the H value
		colourPickerShade.SetColour( hAngle ); // using H value
		
		// set pointer position
		hPointer.position = dir.normalized * 4.5;
	}
	else if ( Input.GetMouseButtonUp(0) )
	{
		myState = PickerState.Idle;
	}
}

… and to set the shade. ( Again, some really bad hard-coded numbers. These are just because I knew my object was 5x5 with center 2.5x2.5 )

function SetMaterialColour() 
{
	s = ( svPointer.position.x + 2.5 ) / 5.0; // get a value for S betweeen 0 and 1
	v = ( svPointer.position.y + 2.5 ) / 5.0; // get a value for V betweeen 0 and 1
	colourOutputObject.material.color = colourCalc.HSVtoRGB( hAngle, s, v ); // convert to RGB colour, and apply to colourOutputObject
}

… and here is the colour calculator. It is just my translation from this link : Color Conversion Algorithms
Once I realized the star variables were the returned values, it all fell into place ! This should probably be a static class or something that can be universally readable.

//------------------------------//
//  ColourCalculator.js         //
//  Written by Alucard Jay      //
//  7/17/2013                   //
//------------------------------//
//  source :
//  http://www.cs.rit.edu/~ncs/color/t_convert.html
/*
RGB to HSV  HSV to RGB

The Hue/Saturation/Value model was created by A. R. Smith in 1978. 
It is based on such intuitive color characteristics as tint, shade and tone (or family, purety and intensity). 
The coordinate system is cylindrical, and the colors are defined inside a hexcone. 
The hue value H runs from 0 to 360º. 
The saturation S is the degree of strength or purity and is from 0 to 1. 
Purity is how much white is added to the color, so S=1 makes the purest color (no white). 
Brightness V also ranges from 0 to 1, where 0 is the black.
*/
// ----

#pragma strict


// ----


function HSVtoRGB( h : float, s : float, v : float ) : Color
{
	var calcColour : Color = new Color( 1, 1, 1, 1 );
	
	var i : int = 0;
	
	var f : float = 0.0;
	var p : float = 0.0;
	var q : float = 0.0;
	var t : float = 0.0;
	
	// achromatic (grey)
	if ( s == 0 )
	{
		calcColour.r = v;
		calcColour.g = v;
		calcColour.b = v;
		
		return calcColour;
	}
	
	// 
	h /= 60.0;
	i = Mathf.FloorToInt( h );
	f = h - i;
	p = v * ( 1.0 - s );
	q = v * ( 1.0 - ( s * f ) );
	t = v * ( 1.0 - ( s * ( 1.0 - f ) ) );

	// 
	switch( i ) 
	{
		case 0 : 
			calcColour.r = v;
			calcColour.g = t;
			calcColour.b = p;
		break;
		
		case 1 : 
			calcColour.r = q;
			calcColour.g = v;
			calcColour.b = p;
		break;
		
		case 2 : 
			calcColour.r = p;
			calcColour.g = v;
			calcColour.b = t;
		break;
		
		case 3 : 
			calcColour.r = p;
			calcColour.g = q;
			calcColour.b = v;
		break;
		
		case 4 : 
			calcColour.r = t;
			calcColour.g = p;
			calcColour.b = v;
		break;
		
		default : 
			calcColour.r = v;
			calcColour.g = p;
			calcColour.b = q;
		break;
	}
	
	// 
	return calcColour;
}


// ----


function RGBtoHSV( r : float, g : float, b : float ) : Vector3
{
	var calcColour : Vector3 = new Vector3( 0, 1, 0 ); // H, S, V
	
	var min : float = 0.0;
	var max : float = 0.0;
	var delta : float = 0.0;
	
	//
	min = Mathf.Min( r, g, b );
	max = Mathf.Max( r, g, b );
	calcColour.z = max; // V
	
	delta = max - min;
	
	if ( max != 0 )
	{
		calcColour.y = delta / max; // S
	}
	else
	{
		// r = g = b = 0
		calcColour.y = 0; // S
		calcColour.x = -1; // H
		
		return calcColour;
	}
	
	//
	if ( r == max ) 
	{
		calcColour.x = ( g - b ) / delta; // H
	}
	else if ( g == max ) 
	{
		calcColour.x = 2.0 + ( ( b - r ) / delta ); // H
	}
	else 
	{
		calcColour.x = 4.0 + ( ( r - g ) / delta ); // H
	}
	
	//
	calcColour.x *= 60.0; // H
	
	if ( calcColour.x < 0 )
	{
		calcColour.x += 360.0;
	}
	
	
	// 
	return calcColour;
}


// ----


function RGBtoHSV( theColour : Color ) : Vector3
{
	var r : float = theColour.r;
	var g : float = theColour.g;
	var b : float = theColour.b;
	
	var calcColour : Vector3 = new Vector3( 0, 1, 0 ); // H, S, V
	
	var min : float = 0.0;
	var max : float = 0.0;
	var delta : float = 0.0;
	
	//
	min = Mathf.Min( r, g, b );
	max = Mathf.Max( r, g, b );
	calcColour.z = max; // V
	
	delta = max - min;
	
	if ( max != 0 )
	{
		calcColour.y = delta / max; // S
	}
	else
	{
		// r = g = b = 0
		calcColour.y = 0; // S
		calcColour.x = -1; // H
		
		return calcColour;
	}
	
	//
	if ( r == max ) 
	{
		calcColour.x = ( g - b ) / delta; // H
	}
	else if ( g == max ) 
	{
		calcColour.x = 2.0 + ( ( b - r ) / delta ); // H
	}
	else 
	{
		calcColour.x = 4.0 + ( ( r - g ) / delta ); // H
	}
	
	//
	calcColour.x *= 60.0; // H
	
	if ( calcColour.x < 0 )
	{
		calcColour.x += 360.0;
	}
	
	
	// 
	return calcColour;
}


// ----

Thanks alucardj , just wanted to know how it worked. :slight_smile:

Wow, would love to see a package for easy importing :slight_smile:

btw, alucardj I sent you a pm on a different matter which I hope you can help me with, thanks!