PS1 Shader

This is a shader trying to emulate the look of a PS1 game. The PS1 graphics pipeline took a lot of shortcuts, for example it used exclusively integers.

Simply apply it to any mesh. Best used with a texture with disabled filtering.


Jitter – The amount of polygon “jitter”, higher value means more intensive jittering.
Jitter Z Coordinate – If disabled, the Z axis (depth) of a vertex isn’t affected. Can avoid some clipping.
Jitter Depth Independent – If disabled, makes further objects jitter less, basically “scaling” the jitter with distance.
Affine Texture Mapping – If disabled, gets rid of the “weird floaty textures” effect at oblique angles. PS1 developers counteracted this by subdividing geometry, so you should too.

Shader code
shader_type spatial;
render_mode vertex_lighting, skip_vertex_transform, 
			specular_phong, diffuse_lambert_wrap;

uniform sampler2D albedo: hint_black_albedo;
uniform sampler2D specular: hint_black;
uniform sampler2D emission: hint_black;

uniform float jitter: hint_range(0.0, 1.0) = 0.5;
uniform bool jitter_z_coordinate = true;
uniform bool jitter_depth_independent = true;
uniform bool affine_texture_mapping = true;
uniform float alpha_scissor: hint_range(0.0, 1.0) = 1.0;

void vertex() {
	float z_orig = VERTEX.z;
	float i = (1.0 - jitter) * min(VIEWPORT_SIZE.x, VIEWPORT_SIZE.y) / 2.0;
	if (jitter_depth_independent) {
		float w = (PROJECTION_MATRIX * vec4(VERTEX, 1.0)).w;
		VERTEX = round(VERTEX / w * i) / i * w;
	} else {
		VERTEX = round(VERTEX * i) / i;
	if (!jitter_z_coordinate) {
		VERTEX.z = z_orig;

	if (affine_texture_mapping) {
		UV *= VERTEX.z;

void fragment() {
	vec2 uv = UV;
	if (affine_texture_mapping) {
		uv /= VERTEX.z;
	ALBEDO = texture(albedo, uv).rgb;
	ALPHA = texture(albedo, uv).a;
	ALPHA_SCISSOR = alpha_scissor;
	EMISSION = texture(emission, uv).rgb;
	SPECULAR = texture(specular, uv).r;
ps1, retro

More from Mighty Duke

PS1 Post-processing

Mandelbrot Set

Related shaders

PS1 Post-processing

2D Hologram Shader

Half-Tone Comic Shader

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.
Inline Feedbacks
View all comments