- Home /
lerp in shader doesn't work as imagined?
Hey, so I'm using lerp in a displacement/tessellation/paralax shader and I'm trying to pulsate between a minimum and maximum float value using _SinTime like this:
_DisplacementAmount = lerp(_MinDisplacement,_MaxDisplacement, _SinTime.w*_PulseSpeed);
However influencing _SinTime in anyway (for example multiplying by _PulseSpeed), doesn't make the process go faster/slower, but instead increases/decreases the maximum and minimum values. I know Mathf.Lerp in Unity C# uses a 0-1 value to interpolate between two values, but this seems to work in a different manner?
Does anyone know why it does this or what the proper way to use it is?
Answer by Bunny83 · Nov 16, 2017 at 01:14 PM
Lerp works everywhere the same way. If it doesn't it's not linear interpolation.
The behaviour you see is absolute correct. Lerp requires a value between 0 and 1. When you multiply _SinTime.w by a value you change that range. Of course this doesn't change the speed of the sine wave.
_SinTime contains 4 values which are
_SinTime.x = Mathf.Sin(Time.time / 8);
_SinTime.y = Mathf.Sin(Time.time / 4);
_SinTime.z = Mathf.Sin(Time.time / 2);
_SinTime.w = Mathf.Sin(Time.time);
If you want to change the frequency of the sine wave you have to change the "time" value inside the sin method. _SinTime just provides 4 predefined values with 4 different constant frequencies (8Hz, 4Hz, 2Hz, 1Hz)
If you want to control the frequency with a parameter you have to do this in your shader:
DisplacementAmount = lerp(_MinDisplacement,_MaxDisplacement, sin(_Time.y *_PulseSpeed));
ps: If you fear the "sin" inside the fragment shader could cause performance issues you can do the same that Unity does, set your own precalculated "sine parameter" from script every frame.
Also keep in $$anonymous$$d that "sin" returns a value between "-1" and "1". The "lerp" inside shaders is not clamped to the range 0 - 1. So a value of "-1" would return a value below your _$$anonymous$$inDisplacement. Specifically it would return _$$anonymous$$inDisplacement*2 -_$$anonymous$$axDisplacement
If you just want to bounce between 0 and 1 you have to use
(0.5 +sin(_Time.y *_PulseSpeed) * 0.5)
Works like a charm. However this DOES indicate that it doesn't work the same everywhere, since it's not clamped within the shader (which also explains the behaviour it was showing).
Thanks for the clarification!