Bounding Battle Background

The Ultimate Earthbound Battle Background Shader! (…Maybe?)

 

Bounding Battle Background is an Earthbound-inspired shader to make your battle backgrounds (Or any backgrounds) more trippy!

This shader aims to be the ultimate all-in-one battle background shader for your Earthbound-inspired games! All and any feedback is welcome!

 

Instructions

Apply the shader to your texture node of your preference and mess with the uniforms as much as your heart content until you get a good result!

 

Recommended texture imports:

  • Repeat:Enabled/Mirrored

 

  • Filter:Unfiltered Palettes if you want a smooth texture cycle

 

Palette Cycling:

  • The texture needs to be Black and White
  • The palette has to be a single pixel

Recommended addon:

  • Export Categories (Godot 3)

 

Uniforms

 

Settings:

  • SNES Transparency Makes it so the horizontal waves alternates like Earthbound’s backgrounds
  • GBA Transparency Makes it so the background makes a transparent duplicate
  • Horizontal Scan-Line Shows horizontal scan-lines
  • Vertical Scan-Line Shows vertical scan-lines
  • Enable Palette Cycling Enables palette cycling

 

Sprite Scroll:

  • Sprite Scroll Direction The direction of the sprite’s scroll
  • Sprite Scroll Speed The speed of the sprite’s scroll

 

GBA Transparency:

  • GBA Transparency Scroll Direction The direction of the duplicates’s scroll
  • GBA Transparency Scroll Speed The direction of the duplicates’s scroll
  • GBA Transparency Value The transparency of the duplicate

 

Horizontal Wave:

  • Horizontal Wave Amplitude The amplitude of the horizontal waves
  • Horizontal Wave Frequency The frequency of the horizontal waves
  • Horizontal Wave Speed The speed of the horizontal waves

 

Vertical Wave:

  • Vertical Wave Amplitude The amplitude of the vertical waves
  • Vertical Wave Frequency The frequency of the vertical waves
  • Vertical Wave Speed The speed of the vertical waves

 

Horizontal Deform:

  • Horizontal Deform Amplitude The amplitude of the horizontal deformation
  • Horizontal Deform Frequency The frequency of the horizontal deformation
  • Horizontal Deform Speed The speed of the horizontal deformation

 

Vertical Deform:

  • Vertical Deform Amplitude The amplitude of the vertical deformation
  • Vertical Deform Frequency The frequency of the vertical deformation
  • Vertical Deform Speed The speed of the vertical deformation

 

Size:

  • Width The width of the texture
  • Height The width of the texture

 

Palette Cycling:

  • Palette Cycling Speed The speed of the palette cycling
  • Palette A texture of the backgrounds palette

 

Sorry if this description came out rushed, i was in quite a pickle with the ticking clock that was my laptop’s battery and my laptop refusing to charge.

 

Extra shader codes

 

Godot 3:

shader_type canvas_item;

// Bounding Battle Backgound shader by Youkuri, this shader is under the Creative Commons license so feel free to use it to your heart contents! No need of crediting or anything.
// NOTE: Filter *does* matter when it comes to palette cycling, Filtered sprites makes it look smoother and Unfiltered makes them change in an instant



uniform float _c_Settings;
uniform bool snes_transparency = false;
uniform bool gba_transparency = false;
uniform bool horizontal_scan_line = false;
uniform bool vertical_scan_line = false;
uniform bool enable_palette_cycling = false;


uniform float _c_Sprite_Scroll;
uniform vec2 sprite_scroll_direction = vec2(0.0, 0.0);
uniform float sprite_scroll_speed = 0.01;


uniform float _c_GBA_Transparency;
uniform vec2 gba_transparency_scroll_direction = vec2(0.0, 0.0);
uniform float gba_transparency_scroll_speed = 0.01;
uniform float gba_transparency_value : hint_range(0.0, 1.0) = 0.5;


uniform float _c_Horizontal_Wave;
uniform float horizontal_wave_amplitude = 0.0;
uniform float horizontal_wave_frequency = 0.0;
uniform float horizontal_wave_speed = 1.0;

uniform float _c_Vertical_Wave;
uniform float vertical_wave_amplitude = 0.0;
uniform float vertical_wave_frequency = 0.0;
uniform float vertical_wave_speed = 1.0;


uniform float _c_Horizontal_Deform;
uniform float horizontal_deform_amplitude = 0.0;
uniform float horizontal_deform_frequency = 0.0;
uniform float horizontal_deform_speed = 1.0;


uniform float _c_Vertical_Deform;
uniform float vertical_deform_amplitude = 0.0;
uniform float vertical_deform_frequency = 0.0;
uniform float vertical_deform_speed = 1.0;


uniform float _c_Size;
uniform float width = 0.0;
uniform float height = 0.0;


uniform float _c_Palette_Cycling;
uniform float palette_cycling_speed = 0.1;
uniform sampler2D palette;



float calculate_diff(float uv, float amp, float freq, float spd){
	float diff_x = amp * sin((freq * uv) + (TIME * spd));
	return diff_x;
}

vec2 calculate_move(vec2 dir, float spd){
	vec2 move = dir * TIME*sprite_scroll_speed;
	return move;
}


void fragment(){
	
	float def_x = calculate_diff(UV.x, horizontal_deform_amplitude, horizontal_deform_frequency, horizontal_deform_speed);
	float def_y = calculate_diff(UV.y, vertical_deform_amplitude, vertical_deform_frequency, vertical_deform_speed);
	float wav_x = calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
	float wav_y = calculate_diff(UV.x, vertical_wave_amplitude, vertical_wave_frequency, vertical_wave_speed);
	
	vec2 move = calculate_move(sprite_scroll_direction, sprite_scroll_speed);
	
	
	if ( int( UV.y * height ) % 2 == 0 && snes_transparency)
	{
		
		wav_x = -wav_x;
		
	}
	
	
	vec4 textube = texture(TEXTURE, vec2(UV.x+def_x + wav_x, UV.y+def_y + wav_y) + move);
	
	
	if (gba_transparency)
	{
		
		float copy_wav_x = -calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
		vec4 tex_copy;
		
		
		if ( int( UV.y * height ) % 2 == 1 && snes_transparency)
		{
			
			copy_wav_x = -copy_wav_x;
			
		}
		
		if (gba_transparency_scroll_direction != vec2(0.0))
		{
			
			vec2 copy_move = calculate_move(gba_transparency_scroll_direction, gba_transparency_scroll_speed);
			tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + copy_move);
			
		}
		else tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + move);
		
		
		textube = mix(textube, tex_copy, gba_transparency_value);
		
	}
	
	
	float palette_swap = mod(textube.r - TIME*palette_cycling_speed, 1.0);
	
	
	if (enable_palette_cycling)
	{
		
		textube = vec4(texture(palette, vec2(palette_swap, 0)).rgb, textube.a);
		
	}
	
	COLOR = textube;
	
	if (horizontal_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.y * height) % 2));
	if (vertical_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.x * width) % 2));
	
}

 

Godot 4 (Without Global Size):

shader_type canvas_item;

// Bounding Battle Backgound shader by Youkuri, this shader is under the Creative Commons license so feel free to use it to your heart contents! No need of crediting or anything.
// NOTE: Filter *does* matter when it comes to palette cycling, Filtered sprites makes it look smoother and Unfiltered makes them change in an instant



group_uniforms Settings;
uniform bool snes_transparency = false;
uniform bool gba_transparency = false;
uniform bool horizontal_scan_line = false;
uniform bool vertical_scan_line = false;
uniform bool enable_palette_cycling = false;


group_uniforms Sprite_Scroll;
uniform vec2 sprite_scroll_direction = vec2(0.0, 0.0);
uniform float sprite_scroll_speed = 0.01;


group_uniforms GBA_Transparency;
uniform vec2 gba_transparency_scroll_direction = vec2(0.0, 0.0);
uniform float gba_transparency_scroll_speed = 0.01;
uniform float gba_transparency_value : hint_range(0.0, 1.0) = 0.5;


group_uniforms Horizontal_Wave;
uniform float horizontal_wave_amplitude = 0.0;
uniform float horizontal_wave_frequency = 0.0;
uniform float horizontal_wave_speed = 1.0;

group_uniforms Vertical_Wave;
uniform float vertical_wave_amplitude = 0.0;
uniform float vertical_wave_frequency = 0.0;
uniform float vertical_wave_speed = 1.0;


group_uniforms Horizontal_Deform;
uniform float horizontal_deform_amplitude = 0.0;
uniform float horizontal_deform_frequency = 0.0;
uniform float horizontal_deform_speed = 1.0;


group_uniforms Vertical_Deform;
uniform float vertical_deform_amplitude = 0.0;
uniform float vertical_deform_frequency = 0.0;
uniform float vertical_deform_speed = 1.0;


group_uniforms Size;
uniform float width = 0.0;
uniform float height = 0.0;


group_uniforms Palette_Cycling;
uniform float palette_cycling_speed = 0.1;
uniform sampler2D palette;



float calculate_diff(float uv, float amp, float freq, float spd){
	float diff_x = amp * sin((freq * uv) + (TIME * spd));
	return diff_x;
}

vec2 calculate_move(vec2 dir, float spd){
	vec2 move = dir * TIME*sprite_scroll_speed;
	return move;
}


void fragment(){
	
	float def_x = calculate_diff(UV.x, horizontal_deform_amplitude, horizontal_deform_frequency, horizontal_deform_speed);
	float def_y = calculate_diff(UV.y, vertical_deform_amplitude, vertical_deform_frequency, vertical_deform_speed);
	float wav_x = calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
	float wav_y = calculate_diff(UV.x, vertical_wave_amplitude, vertical_wave_frequency, vertical_wave_speed);
	
	vec2 move = calculate_move(sprite_scroll_direction, sprite_scroll_speed);
	
	
	if ( int( UV.y * height ) % 2 == 0 && snes_transparency)
	{
		
		wav_x = -wav_x;
		
	}
	
	
	vec4 textube = texture(TEXTURE, vec2(UV.x+def_x + wav_x, UV.y+def_y + wav_y) + move);
	
	
	if (gba_transparency)
	{
		
		float copy_wav_x = -calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
		vec4 tex_copy;
		
		
		if ( int( UV.y * height ) % 2 == 1 && snes_transparency)
		{
			
			copy_wav_x = -copy_wav_x;
			
		}
		
		if (gba_transparency_scroll_direction != vec2(0.0))
		{
			
			vec2 copy_move = calculate_move(gba_transparency_scroll_direction, gba_transparency_scroll_speed);
			tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + copy_move);
			
		}
		else tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + move);
		
		
		textube = mix(textube, tex_copy, gba_transparency_value);
		
	}
	
	
	float palette_swap = mod(textube.r - TIME*palette_cycling_speed, 1.0);
	
	
	if (enable_palette_cycling)
	{
		
		textube = vec4(texture(palette, vec2(palette_swap, 0)).rgb, textube.a);
		
	}
	
	COLOR = textube;
	
	if (horizontal_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.y * height) % 2));
	if (vertical_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.x * width) % 2));
	
}
Shader code
shader_type canvas_item;

// Bounding Battle Backgound shader by Youkuri, this shader is under the Creative Commons license so feel free to use it to your heart contents! No need of crediting or anything.
// NOTE: Filter *does* matter when it comes to palette cycling, Filtered sprites makes it look smoother and Unfiltered makes them change in an instant



group_uniforms Settings;
uniform bool snes_transparency = false;
uniform bool gba_transparency = false;
uniform bool horizontal_scan_line = false;
uniform bool vertical_scan_line = false;
uniform bool enable_palette_cycling = false;


group_uniforms Sprite_Scroll;
uniform vec2 sprite_scroll_direction = vec2(0.0, 0.0);
uniform float sprite_scroll_speed = 0.01;


group_uniforms GBA_Transparency;
uniform vec2 gba_transparency_scroll_direction = vec2(0.0, 0.0);
uniform float gba_transparency_scroll_speed = 0.01;
uniform float gba_transparency_value : hint_range(0.0, 1.0) = 0.5;


group_uniforms Horizontal_Wave;
uniform float horizontal_wave_amplitude = 0.0;
uniform float horizontal_wave_frequency = 0.0;
uniform float horizontal_wave_speed = 1.0;

group_uniforms Vertical_Wave;
uniform float vertical_wave_amplitude = 0.0;
uniform float vertical_wave_frequency = 0.0;
uniform float vertical_wave_speed = 1.0;


group_uniforms Horizontal_Deform;
uniform float horizontal_deform_amplitude = 0.0;
uniform float horizontal_deform_frequency = 0.0;
uniform float horizontal_deform_speed = 1.0;


group_uniforms Vertical_Deform;
uniform float vertical_deform_amplitude = 0.0;
uniform float vertical_deform_frequency = 0.0;
uniform float vertical_deform_speed = 1.0;


group_uniforms Size;
global uniform float width = 0.0;
global uniform float height = 0.0;


group_uniforms Palette_Cycling;
uniform float palette_cycling_speed = 0.1;
uniform sampler2D palette;



float calculate_diff(float uv, float amp, float freq, float spd){
	float diff_x = amp * sin((freq * uv) + (TIME * spd));
	return diff_x;
}

vec2 calculate_move(vec2 dir, float spd){
	vec2 move = dir * TIME*sprite_scroll_speed;
	return move;
}


void fragment(){
	
	float def_x = calculate_diff(UV.x, horizontal_deform_amplitude, horizontal_deform_frequency, horizontal_deform_speed);
	float def_y = calculate_diff(UV.y, vertical_deform_amplitude, vertical_deform_frequency, vertical_deform_speed);
	float wav_x = calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
	float wav_y = calculate_diff(UV.x, vertical_wave_amplitude, vertical_wave_frequency, vertical_wave_speed);
	
	vec2 move = calculate_move(sprite_scroll_direction, sprite_scroll_speed);
	
	
	if ( int( UV.y * height ) % 2 == 0 && snes_transparency)
	{
		
		wav_x = -wav_x;
		
	}
	
	
	vec4 textube = texture(TEXTURE, vec2(UV.x+def_x + wav_x, UV.y+def_y + wav_y) + move);
	
	
	if (gba_transparency)
	{
		
		float copy_wav_x = -calculate_diff(UV.y, horizontal_wave_amplitude, horizontal_wave_frequency, horizontal_wave_speed);
		vec4 tex_copy;
		
		
		if ( int( UV.y * height ) % 2 == 1 && snes_transparency)
		{
			
			copy_wav_x = -copy_wav_x;
			
		}
		
		if (gba_transparency_scroll_direction != vec2(0.0))
		{
			
			vec2 copy_move = calculate_move(gba_transparency_scroll_direction, gba_transparency_scroll_speed);
			tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + copy_move);
			
		}
		else tex_copy = texture(TEXTURE, vec2(UV.x+def_x + copy_wav_x, UV.y+def_y + wav_y) + move);
		
		
		textube = mix(textube, tex_copy, gba_transparency_value);
		
	}
	
	
	float palette_swap = mod(textube.r - TIME*palette_cycling_speed, 1.0);
	
	
	if (enable_palette_cycling)
	{
		
		textube = vec4(texture(palette, vec2(palette_swap, 0)).rgb, textube.a);
		
	}
	
	COLOR = textube;
	
	if (horizontal_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.y * height) % 2));
	if (vertical_scan_line) COLOR = mix(vec4(0.0, 0.0, 0.0, 1.0), COLOR, float(int(UV.x * width) % 2));
	
}
Tags
background, battle, earthbound, mother, texture, trippy, wave, wobble
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Earthbound-like battle background shader w/scroll effect and palette cycling

page flip with transparent background

Tiling Dot Background

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
spkbreadroll
9 months ago

this is really neat!!
more than an excuse to get started on a JRPG myself!

Lumine_GDX17
6 months ago

does this work on godot 4?