- Home /
Font Color changing shader [color changes based on what background color is]
I want to create an effect to make text easier to read on progress bars. I want an effect similar to this:
I know I need to use a shader, and then just check the background color, and output the color I want in my fragment program.
Here is my current shader that takes in an input color, and based on a threshold color (right now it is right in the middle of rgba values as I want) and then changes my output color to black or white.
Shader "FontEffects/InvertColor"
{
Properties
{
//grey
_ColorThreshhold ("Color Threshhold", Color) = (0.5, 0.5, 0.5,1.0)
//White
_BelowThreshhold ("Below Threshhold Color", Color) = (1.0,1.0,1.0,1.0)
//Black
_AboveThreshhold ("Above Threshhold Color", Color) = (0.0,0.0,0.0,1.0)
_InputColor ("Input Color", Color) = (0.0,0.0,0.0,1.0)
//declare a color here to save background to, how do I do this?
}
SubShader
{
Pass
{
//save color of background sample here into a float4
}
Pass
{
CGPROGRAM
//pragmas
#pragma vertex vert
#pragma fragment frag
//user defined vars
uniform float4 _ColorThreshhold;
uniform float4 _BelowThreshhold;
uniform float4 _AboveThreshhold;
uniform float4 _InputColor;
//base input structs
struct vertexInput
{
float4 vertex : POSITION;
float4 vColor : COLOR0;
};
struct vertexOutput
{
float4 pos : SV_POSITION;
float4 vColor : COLOR;
};
//vertex function
vertexOutput vert(vertexInput v)
{
vertexOutput o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
return o;
}
//fragment function
float4 frag(vertexOutput i) : COLOR
{
float sum = _InputColor.r + _InputColor.g + _InputColor.b;
float tSum = _ColorThreshhold.r + _ColorThreshhold.g + _ColorThreshhold.b;
if(sum >= tSum)
{
//above threshhold
return _AboveThreshhold;
}
else
{
//below threshhold
return _BelowThreshhold;
}
}
ENDCG
}
}
//comment out only for debug so errors make object pink
//Fallback "Diffuse"
}
I know I will need to code another pass to grab the color that is behind it (before I render the font) and then use that for the color. For that I believe I just put in the code to declare a pass before my main pass, and then save to a nonUnity exposed variable name. Then I use this in the second pass.
Is this correct? (I want to avoid using shaderlab, and stick to cg to learn cg and work on chips that dont support shaderlab.)
Another question: Is it better to use a half instead of a float4 for rgb values? (less bits to handle in the gpu)? Or are colors handled just fine as float4?
Answer by whydoidoit · Apr 12, 2013 at 11:53 PM
So you should use half rather than float for colours (or indeed fixed if you won't be accessing the individual elements) on platforms that have lower performance - like mobile. It's fine on everything else too really - should be enough precision for most things.
You can use a GrabPass {} to get the current screen into the _GrabTexture texture which you can access from your next pass - guessing you'd want to use the version which takes as name and only grabs once per frame though. http://docs.unity3d.com/Documentation/Components/SL-GrabPass.html
Not sure how you'd do a grab pass without that ShaderLab pass syntax and it's Unity Pro only I believe.
Oh and I guess you'd want to make sure that the queue for the bars was "very late" in the process
Can grabpass (using the efficient text name one) just save the pixel color, and then I change the pixel color in the second pass? If so, how would i do this, and access the color of the pixel from grab pass?
I did look up grab pass on the unity wiki, and am still a bit confused.
Your answer
Follow this Question
Related Questions
Get color of pixel before pass: prefer cg, shaderlab is last resort 0 Answers
Shader - Share values between different pass 0 Answers
Invert Color Shader (without see-through) 0 Answers
Is there a way to set an alpha color? 2 Answers
How do I invert the color of ui text to make it more readable, on a messy background? 4 Answers