Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interpolating a changing value based on time (glsl)

I have a uniform in my vertex shader with a value that can change from 0 to 1, without interpolation. However, I want it interpolated over time, but I don't want to do this in Javascript (from the CPU). I want it interpolated from 0 to 1 (or back) when it changes (which happens on certain user input).

(I do have a incrementing uTime uniform that I suppose I can use for this problem)?

I hope this explains my question clear enough. TIA.

like image 705
Fabian Tjoe A On Avatar asked Oct 22 '25 03:10

Fabian Tjoe A On


1 Answers

I suppose, that uTime contains the time in milliseconds. Dividing the value by a timespan, gives a value that increments by 1 in the timespan.
The fractional part of that value continuously changes from 0.0 to 1.0 and starts again at 0.0. The the fractional part of a number can be computed by fract. e.g:
(if the unit of uTime is secondes, then the timespan has to be 3.0)

uniform float uTime; // time in milliseconds

void main()
{
    const float timespan = 3000.0; // e.g. 3 seconds
    float w = fract(uTime / timespan);

    // [...]
}

For a Hermite interpolation use additionally smoothstep:

uniform float uTime; // time in milliseconds

void main()
{
    const float timespan = 3000.0; // e.g. 3 seconds
    float w = smoothstep(0.0, 1.0, fract(uTime / timespan));

    // [...]
}

Another nice effect can be achieved by using sin. Sine gives a value that continuously changes between -1.0 and 1.0 dependent on the angle in Radian [0.0, 2*PI] e.g.:

uniform float float uTime; // time in milliseconds

void main()
{
    const float timespan = 3000.0; // e.g. 3 seconds
    float w = sin(2.0 * 3.14159 * uTime / timespan) * 0.5 + 0.5;

    // [...]
}

If you want to start the animation at a certain point of time, then you'll need a 2nd uniform variable (uStartTime), which indicates the time point. The variable has to have the same unit than uTime.
When ever the animation has to be started the set the value of uStartTime. At the begin its value is 0. If uStartTime is less or equal uTime then the animation is at 0.0. That is rare case and just for a moment, when uStartTime is set. It uTime is grater or equal than uStartTime + timespan than the animation is at 1.0. Instead of calculating the fractional part, you've to clamp the difference of te current time and the start time to the range form 0.0 to 1.0. e.g.:

uniform float uTime; // time in milliseconds
uniform float uStartTime; 

void main()
{
    const float timespan = 3000.0; // e.g. 3 seconds
    float w = clamp((uTime-uStartTime) / timespan, 0.0, 1.0);

    // [...]
}

If you want to set the interpolation direction(form 0 to 1 or 1 to 0), dependent on the "direction", the you'll need some additional information. Add another uniform variable (uTarget) of type float and set it either to 0.0 or 1.0. The value defines the interpolation target:

uniform float uTime; // time in milliseconds
uniform float uStartTime; 
uniform float uTarget; // 0.0 or 1.0 

void main()
{
    const float timespan = 3000.0; // e.g. 3 seconds
    float w = clamp((uTime-uStartTime) / timespan, 0.0, 1.0);
    w = mix(1.0-w, w, uTarget);

    // [...]
}
like image 106
Rabbid76 Avatar answered Oct 25 '25 11:10

Rabbid76



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!