Home Technical Talk

[Help]Linear Interpolation of Three Values

polycounter lvl 11
Offline / Send Message
YakZSmelk polycounter lvl 11
I'm working on a shader that would use the Alpha to distinguish which RGB channel of a texture to display. My thoughts on how this would work are;

A:1.0 = R, A:0.5 = G, A:0.0 = B,

Is it possible to build this using Linear Interpolation nodes? If not what would be the correct approach?


I'm working with the Strumpy Shader editor in Unity, but I'm more familiar with UDKs material editor, which has an IF node that would be perfect.


Thanks for any help or insight you can provide.

Replies

  • Farfarer
    I'm guessing you meant that last bit to be "A:0.0 = B"?
    If not, replace color.b in this code with 0.

    Something like this should work...
    float a = color.a * 2;
    float r = lerp (color.b, color.g, a);
    a -= 1;
    r = lerp (r, color.r, a);

    You could branch it... but I suspect lerping is easier on the shader. They still don't really like branching much.



    Although if it's to blank out the other channels, you probably want something like...

    float a = color.a * 2;
    float3 r = lerp (float3(0,0,1), float3(0,1,0), a);
    a -= 1;
    r = lerp (r, float3(1,0,0), a);
    r *= color.rgb;
  • almighty_gir
    Offline / Send Message
    almighty_gir ngon master
    edit: nevermind.
  • YakZSmelk
    Offline / Send Message
    YakZSmelk polycounter lvl 11
    @Farfarer

    Thanks that worked perfectly, I did some research after I posted and realized the Step Node is A<=B, which was exactly what I needed.
    triLerp.jpg



    Also I corrected the original post.
  • RN
    Offline / Send Message
    RN sublime tool
    Here is an untested alternative that avoids branching, using the fact that a boolean value can be cast to numeric values in Cg or HLSL.
    const float a = color.a;
    float rR = color.r * (float)( a >= 0.66 && a <= 1.0 );
    float rG = color.g * (float)( a > 0.33 && a < 0.66 );
    float rB = color.b * (float)( a >= 0.0 && a <= 0.33 );
    
    // Then...
    
    float4 rColour = float4( rR, rG, rB, 1.0 );
    
    // Or...
    
    float x = rR + rG + rB;
    float4 rColour = float4( x, x, x, 1.0 ); // Greyscale representation.
    
  • RN
    Offline / Send Message
    RN sublime tool
    Farfarer wrote: »
    float a = color.a * 2;
    float r = lerp (color.b, color.g, a);
    a -= 1;
    r = lerp (r, color.r, a);
    I'm trying to understand something. In Cg or HLSL the Lerp function does not clamp the parameter value used to interpolate, so when the alpha value is 0.0 the result will be surprising.

    When alpha is zero:

    a = 0.0 * 2
    x = lerp( B, G, a ) // x = B
    a -= 1 // a = -1
    x = lerp( x, R, a ) // This is x*(1-a) + R*a

    // x is now 2*B - R. Can someone confirm this?

    I think clamping is needed to avoid this:

    float a = clamp( color.a * 2.0, 0.0, 1.0 );
    float r = lerp ( color.b, color.g, a );
    a = clamp( a - 1.0, 0.0, 1.0 );
    r = lerp( r, color.r, a );

    - http://http.developer.nvidia.com/Cg/lerp.html
    - https://msdn.microsoft.com/en-us/library/windows/desktop/bb509618%28v=vs.85%29.aspx
  • Farfarer
    Oh right, yeah.

    You'll want saturate(a), rather than a inside the lerp then.

    Can't do clamp outside when defining a otherwise you're clamping a value that needs to span a range of 2.
    float a = color.a * 2;
    float r = lerp (color.b, color.g, saturate(a));
    a -= 1;
    r = lerp (r, color.r, saturate(a));
    
  • YakZSmelk
    Offline / Send Message
    YakZSmelk polycounter lvl 11
    Thanks for the continued help guys!

    I am unfamiliar with what Saturate does, I looked through both the UDK and Shaderforge Node guides and can only seem to find Desaturate. Would this work the same way if I inverted the product?
  • RN
    Offline / Send Message
    RN sublime tool
    I understand what you mean. Using Saturate\Clamp only when using 'a' (not when setting its value) is what works.
    YakZSmelk wrote: »
    I am unfamiliar with what Saturate does
    Saturate is a quick way to write Clamp( value, 0.0, 1.0 ). It clamps a value to the range [0, 1].

    Saturate is part of the "intrinsic functions" of the shading language. You can find the documentation (the technical description) for Saturate and other intrinsic functions of Cg -- the shading language that Unity uses -- in this list:
    http://http.developer.nvidia.com/Cg/index_stdlib.html
  • YakZSmelk
    Offline / Send Message
    YakZSmelk polycounter lvl 11
    Kryzon that's a great reference, I'll definitely be reading more into it. The saturation worked great but I now need to toy with the >.5 end of the spectrum.
Sign In or Register to comment.