Shader has trouble splitting textures into pixel-perfect rows

SOLVED! My solution is a bit embarrasing: the screen_height variable was incorrectly set to my screen width…oops.

Even with that simple fix, I did rewrite the shader a fair bit to not rely on the screen_height variable but rather the height of the texture itself. Here it is if you want a look:

/* 
Earthbound battle backgrounds shader with scrolling effect and palette cycling like in the original game.
Original by @r3tr0_dev - https://godotshaders.com/shader/earthbound-like-battle-background-shader-w-scroll-effect-and-palette-cycling/
Modified by @DragonAero
	
Apply the shader to a TextureRect or a Sprite. Use a texture with some shapes in a transparent background for best results.
You can then use a ColorRect or another method to paint the background.
You can use the shader on multiple TextureRects and obtain a double-buffer effect tweaking the values for each one, remember to Make Unique the shader material.
*/
shader_type canvas_item;

/**
Determines whether the background has transparent lines or not.
*/
uniform bool enable_scan_lines = false;

/**
How tall each scanline should be, in pixels.
For best results, set this to a value that can cleanly divide the texture height into a whole number.
*/
uniform float scanline_height = 1;

/**
The direction of the infinite scrolling effect. Set this to (0, 0) to disable the effect.
*/
uniform vec2 scroll_direction = vec2(0.0, 0.0);

/**
The speed of the infinite scrolling effect.
*/
uniform float scrolling_speed = 0.08;

/**
Enables interleaved oscillation on the x-axis.
*/
uniform bool interleaved_oscillation = false;

/**
The amplitude of the oscillation effect.
*/
uniform vec2 amplitude = vec2(0.075, 0.0);

/**
The frequency of the oscillation effect.
*/
uniform vec2 frequency = vec2(10.0, 0.0);

/**
The speed of the oscillation effect.
*/
uniform vec2 speed = vec2(2.0, 0.0);

/**
Enables the palette cycling effect using a palette to change the color of a grayscale background based on a palette of colors, like in the original game with some backgrounds.
*/
uniform bool enable_palette_cycling = false;

/**
The gradient texture used for the palette cycling effect. The number of the palette colors must correspond with the grayscale of the base texture for best results.
*/
uniform sampler2D palette;

/**
The speed of the palette cycling.
*/
uniform float palette_speed = 0.1;

void fragment()
{
	vec2 texture_size = 1.0 / TEXTURE_PIXEL_SIZE;
	
	float diff_x = amplitude.x * sin((frequency.x * UV.y) + (speed.x * TIME));
	float diff_y = amplitude.y * sin((frequency.y * UV.y)  + (speed.y * TIME));
	
	vec2 scroll = scroll_direction * TIME * scrolling_speed;
	
	vec4 tex = texture(TEXTURE, vec2(UV.x + ((int(UV.y * (texture_size.y / float(scanline_height))) % 2) == 0 && interleaved_oscillation ? -diff_x : diff_x), UV.y + diff_y) + scroll);
	
	float palette_swap = mod(tex.r - TIME * palette_speed, 1.0);
	
	if (enable_palette_cycling)
	{
		COLOR = vec4(texture(palette, vec2(palette_swap, 0)).rgb, tex.a);
	} else {
		COLOR = tex;
	} 
	
	if (enable_scan_lines) {
		COLOR = mix(vec4(0.0), COLOR, float(int(UV.y * (texture_size.y / float(scanline_height))) % 2));
	}
}