N64 Style Skybox

Single-image skybox as seen in some N64 and PS1 games. I’ve always enjoyed this effect but found surprisingly little information about it, so I decided to recreate it myself.

This works as a spatial shader, so you can apply it to a skybox object surrounding the scene. It’s also possible to implement as a proper sky shader, you just have to get the camera’s rotation from a script since sky shaders don’t have access to the view matrix.

Shader code
shader_type spatial;
render_mode unshaded;

uniform sampler2D sky_texture : source_color;
uniform bool lock_aspect = false;
uniform float aspect_ratio = 1.3333333;
uniform vec2 fov = vec2(180.0, 90.0);
uniform ivec2 tiling = ivec2(1, 1);
uniform vec2 offset = vec2(0.0, 0.0);

varying vec2 BG_COORDS;
varying vec2 BG_SCALE;

void vertex() {
	//Camera YX rotation per Basis.get_euler source code
	float y = atan(VIEW_MATRIX[0][2], VIEW_MATRIX[2][2]);
	float x = asin(VIEW_MATRIX[1][2]);
	
	//Map rotation to screen space
	BG_COORDS = vec2(y * 0.5, -x) * -(1.0 / PI);
	BG_COORDS.y += 0.5;
	
	BG_SCALE.y = fov.y * (1.0 / 180.0);
	BG_SCALE.x = !lock_aspect ? 
		fov.x * (1.0 / 360.0) : 
		VIEWPORT_SIZE.x / (VIEWPORT_SIZE.y * aspect_ratio) * BG_SCALE.y;
	
	//Keep background centered vertically when FOV changes
	BG_COORDS.y *= BG_SCALE.y > 1.0 ? 0.0 : 1.0 - BG_SCALE.y;
}

void fragment() {
	vec2 uv_offset = vec2(-offset.x, offset.y);
	vec2 uv = (SCREEN_UV + uv_offset) * BG_SCALE + BG_COORDS;
	uv *= vec2(tiling);
	ALBEDO = texture(sky_texture, uv).rgb;
}
Tags
N64, ps1, retro, sky, skybox
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

N64 Style Metallic

Skybox from 6 textures

3D Edge Detection Shader (Borderlands-Style)

Subscribe
Notify of
guest

7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Peter
Peter
3 months ago

Can someone explain how to use it, i dont understand it

Purpbat
Purpbat
2 months ago
Reply to  tentabrobpy

could you offer the template texture you used in the gif? that looks very helpful incase you wanna make custom backgrounds

Elsenyh
1 month ago

Godot 3.5???

Akeem
Akeem
1 month ago

This works perfectly, thank you! But I have a question – is it possible to use nearest neighbor interpolation instead of linear interpolation here?

elvisish
13 days ago
Reply to  Akeem

Replace:

uniform sampler2D sky_texture : source_color;

with:

uniform sampler2D sky_texture : source_color, filter_nearest;