Search Unity

Shader "Main Color" vs. _Color using SetColor()

Discussion in 'Shaders' started by JeffersonTD, Mar 24, 2013.

  1. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    I have single plane, with a renderer that has an image and a "Transparent/Bumped Diffuse" shader. Using the inspector I can change the "Main Color" attribute, which lets me manipulate the hue and alpha of the image. Nice. But I would like to temper this "Main Color" through code. How do I do that?

    I have tried this:
    http://docs.unity3d.com/Documentation/ScriptReference/Material.SetColor.html
    using all the four "propertyNames". Like expected using "_Color" will make a change. The problem is that it doesn't have the same effect as changing the Main Color in Inspector: whereas the Main Color just changes the hue and alpha, setting the "_Color" through C# changes the color of the whole visible image, making the image have only one single color.

    I've tried to look for information about this, but every comment about this would seem to imply that _Color should be the same as the Main Color. Yet it doesn't seem to be so. _SpecColor, _Emission and _ReflectColor don't seem to be right either. What am I not getting here?
     
  2. dasbin

    dasbin

    Joined:
    Jan 14, 2012
    Posts:
    261
    Normally _Color is Main Color (which is just a label). Just open up the shader code and you will see the label and _Color defined in the first few lines of code, so you know what is what.

    In other words, in most cases, it should have the exact same effect whether set via code or the inspector. I suspect something else is going on as well.
     
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Just use Material.color. No reason to bother with SetColor for that property. Show your code; your code or asset is the problem.
     
  4. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    This is probably a silly question, but what do you mean by "open up the shader code"? Can I somehow see the shader source code?


    Yes, the only reason why I was using SetColor was because just setting color directly didn't seem to work as I wanted it to. SetColor allowed me to try the other options which also didn't seem to work. Here's how I set it:

    Code (csharp):
    1. transform.GetChild (0).renderer.material.SetColor("_Color", new Color(255f,0f,0f,alpha));
    2.  
    or alternatively of course:
    Code (csharp):
    1. transform.GetChild (0).renderer.material.color = new Color(255f,0f,0f,1f);
    As a result it appears fully red, unlike when setting the "Main Color".
     
  5. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    That codes sets the color to be 255 times as saturated as the slider allows. Use Color32 if you want to work with bytes. Color uses floats in the 0-1 range. There's not going to be a case were you want both a value above 1, AND an "f", like you have there.
     
  6. JeffersonTD

    JeffersonTD

    Joined:
    Feb 5, 2013
    Posts:
    268
    Ah, but of course, that's it. I should have read the documentation for color which quite clearly states "Each color component is a floating point value with a range from 0 to 1." I was just somehow determined that I was doing something wrong otherwise. :)

    Thanks for the replies to both of you!
     
  7. SamohtVII

    SamohtVII

    Joined:
    Jun 30, 2014
    Posts:
    370
    Same issue and was pulling my hair out. Thanks for the answer. Saved a lot of unneeded stress.

    Eventually used this:

    Code (CSharp):
    1. public static Vector4 hexColor(float r, float g, float b, float a){
    2.          Vector4 color = new Vector4(r/255, g/255, b/255, a/255);
    3.          return color;
    4.      }
    5.  
    6. public void chageTheCarColor(string stats) {
    7.         Color newColor = hexColor(int.Parse(stats.Substring(0,3)), int.Parse(stats.Substring(3,3)), int.Parse(stats.Substring(6,3)), 255);
    8.         theCar[currentCar].GetComponent<Transform>().GetChild(1).GetComponent<Renderer>().material.SetColor("_Color", newColor);
    9.     }
    10.  
    11.  
    12.  
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    You can use the built in Color32 instead:
    https://docs.unity3d.com/ScriptReference/Color32.html
    Code (csharp):
    1. Color32 newColor = new Color32(63, 127, 191, 255);
    2. mat.SetColor("_Color", newColor);
    The SetColor() function does not actually take a Color32 input, but Color and Color32 are implicit casts and can be used interchangeably. Just be aware it isn't free, it's doing the same conversion your code example is doing, and going from Color to Color32 may cause you to lose data as Color32 clamps values >1.0 as well as being a byte rather than a float.
    https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Color32.cs
     
    glenneroo likes this.