When using shader script to scroll background how can you make it not jump when stopping/restarting scrolling

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By bribat123

Hello,

I am using the following shader script to automatically scroll the background in my game:

uniform float scroll_speed = 0;

void fragment()
{
vec2 shiftedUV = UV;
shiftedUV.x += TIME * scroll_speed;
vec4 color = texture(TEXTURE, shiftedUV);
COLOR = color;
}

The script works fine when scrolling is on, however when scrolling is stopped or restarted the texture appears to jump. How can I eliminate the jumping?

Thank you!

:bust_in_silhouette: Reply From: Motshew

The reason it snaps around like that when you continue the shader is because TIME is still moving, even when the shader is paused. So the shader isn’t moving, but the variables are.

I had the same issue, here’s what I did.
this code was for a continuously scrolling down background.

here’s the shader code.

shader_type canvas_item;

uniform vec2 direction = vec2(0.0, -1.0);
uniform float speed_scale = 0.5;
uniform float time;

void fragment() {
	
	vec2 move = direction * time * speed_scale;
	
	COLOR = texture(TEXTURE, UV + move);
	
}

I replaced TIME with the variable time. then I’ll pass my own controlled delta time into the shader from my GDScript.

var is_paused = false
var time = 0

func _process(delta):
	if is_paused == false:
		$Background.get_material().set_shader_param("time", time)
		time += delta
	else:
		return

We make a check for if the shader is supposed to be paused, if not then the time variable will be updated in the shader. Then we add delta and do it again. It should behave just like using TIME in the shader code.

If the shader is supposed to be paused, then we stop updating time and stop updating the shader.

now when we resume and change ‘is_paused’ to false, the shader will start moving from where it was before.

Its works perfect. But, how much does it degrade performance? If i create layers array and will setting time for all layers in _process? ( my current layers number of is 4 )


export (Array,NodePath) onready var layers
func _process(delta):
    if is_paused == false:
	    for layer in layers:
		    get_node(layer).get_material().set_shader_param("time",time)
		    time += delta
    else:
	    return

MiroslavH | 2023-02-23 17:22