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));
}
this is really neat!!
more than an excuse to get started on a JRPG myself!
does this work on godot 4?