Search Unity

Get Gradient Time from Color

Discussion in 'Scripting' started by poolts, May 2, 2015.

  1. poolts

    poolts

    Joined:
    Aug 9, 2012
    Posts:
    113
    Hi,

    I'm trying to work out how to get the gradient time (0% - 100%) from a color.

    Basically trying to work out this: public float GetGradientTime(Color c) - which will return a percentage where the color falls on the gradient (i.e. if the gradient was blue -> green -> red -> yellow and I passed it a colour between blue and green, it should return 15%-ish).

    It's pretty much the opposite of the existing method for gradients which is public Color Evaluate(float time)

    I'm thinking about iterating through the ColorKeys of the gradient and find the closest match to a color then return the time of that color key? Not sure if this is the best solution.

    Many thanks, Alex.
     
  2. ilya_m_3ds

    ilya_m_3ds

    Joined:
    Jan 15, 2020
    Posts:
    9
    Bumping this. This is also a feature that I'd like
     
  3. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    This is solution if you have more than 2 GradientColorKey.
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,113
    Colors cannot be matched directly like that.

    Three reasons:
    1) because it's highly unlikely that your query color will be exactly equal to anything in the color gradient,
    2) because Color has floating point components and these can't be matched by definition, and
    3) because gradients are continuums, and you can sample them with theoretically indefinite accuracy (bound only by floating point resolution, which is ultimately 2^-27 I believe).

    You could round Color components to an equivalent of Color32 to narrow down the combinatorial space. Or you could introduce some error metric, and try to find the least error. But the real problem is what Gradient actually represents.

    Here are some older posts of mine which illustrate the problem
    Gradient structure
    Combining gradients

    In short, you either need to make a gradient object that is capable of working with discrete concretely defined colors, through hash codes or something similar --or-- you are supposed to make a math-friendly algorithmic solver, because scanning through a floating point continuum doesn't make any sense, performance-wise.

    It's not ultra-hard, but it's still non-trivial, and imo it's just too much work for something that's not really that useful.
     
    Last edited: Oct 27, 2022
    Nad_B likes this.
  5. kruskal21

    kruskal21

    Joined:
    May 17, 2022
    Posts:
    68
    orionsyndrome and Nad_B like this.
  6. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    A quick solution is to simplify the gradient into, lets say x segments (kind of like indexed colors/custom color space) and store them into a
    HashSet<Color>
    /
    List<Color>
    /
    Custom optimized tree
    , then use Euclidean distance between the color and each segment to find the nearest match, by treating RGB components as XYZ in our imaginary coordinates system.

    In Unity terms we create a
    Vector3(R, G, B)
    for each of our indexed colors, calculate (squared) distances (
    Vector3.SqrDistance
    /
    Vector3.Distance
    ) and choose the closest one.

    This should give a good approximation.

    Of course more segments => better precision => slower performance. Testing is needed to have a balance between precision/speed.

    From the top of my head, I'd say 256 is a good number to start with (precision: ~0.39%)
     
    Last edited: Oct 27, 2022
    orionsyndrome likes this.
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,113