Search Unity

Clipping pixels based on the reversed function values and UV's

Discussion in 'Shaders' started by xVergilx, May 21, 2019.

  1. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I wonder if its possible.
    E.g. I've got uv coordinates of a plane / 3d object.
    Is it possible to clip the plane as an opposite of sin() function?

    Madskillz
    uvclip.png
    Where white to be cut out, and red to be left (as a function value).
    Note that texture doesn't contain data of the color to be discarded.

    I want to generate procedural effect by combining multiple math functions.
    So its like a dissolve, but uv / math function based instead of plain noise.

    I've been thinking about plotting the function first and then checking against the uv.x/uv.y.
    But that seems to be waste of resources to do for each pixel.

    Maybe someone can suggest me a least performance impactful algorithm of doing so?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Apart from having that slightly backwards, that's basically what you have to do with shaders.

    Code (csharp):
    1. float s = sin(i.uv.x) * _Scale;
    2. float sd = s - abs(i.uv.y - 0.5);
    3. clip(_LineWidth - abs(sd));
    Calculate your value based on UV.x, get edge on UV.y, clip anything outside of some range from that edge along UV.y.

    For a nicer line, you may need to calculate the value at multiple offsets from the current UV and compare those, otherwise very steep lines will get thin.
     
    Last edited: May 22, 2019
    xVergilx likes this.
  3. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Can't believe its that simple. With a little bit of tweaks that seems to be working.
    How do I combine multiple funtions though? Math is hard :)
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    As you asking this question in terms of "how do I add multiple sine waves together to get a specific look", or "how do I use a more complex function with this technique", or "how do I show multiple functions as separate lines?"

    If it's the middle question, whatever the output of the function is would be the s value in the above code.
    If it's the last question, then calculate each of the lines, storing the value that clip() has in the above example, and then use however many calls of max() needed to get the largest value and pass that into clip().

    If it's the first question ... *shrug* ... that's on you.
     
    xVergilx likes this.
  5. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Its the last one :)
    Using multiple max() might do the trick. I was thinking about using multiple branches but that would be a bad idea.

    I'll try it, thanks.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    If you want different colored lines, then lerp() could also work. However really simple branches get a bad wrap, but really aren't bad at all.

    Code (csharp):
    1. float lineA = _LineWidth - abs(sdA);
    2. float lineB = _LineWidth - abs(sdB);
    3.  
    4. clip(max(lineA, lineB));
    5.  
    6. return lineB >= 0 ? _ColorB : _ColorA;
    If you read anything that says "Never use an if statement in a shader, they're too slow! Instead use sign(), step(), min() or max()", they're wrong because all three of those functions are internally implemented as if statement equivalents. In fact sign() might be slower than whatever you might be doing with an if.
     
    xVergilx likes this.