PSX Drag-&-Drop Shader


Hello all! I got tired having to replace the material’s of my meshes everytime I wanted to apply a PSX style shader. Plus I felt there were some options lacking from other PSX style shaders.

So, I made my own that let’s you drag and drop the shader onto a pre-existing Shader Material.


All you have to do is convert the `StandardMaterial3D` on your `MeshInstance3D` into a `ShaderMaterial`, drop/load the `.gdshader` code in, AND VOILÀ! PSX vector-snapping and affine mapping!

Like other PSX Shaders, you can change the amount of `Jitter` the mesh has, and if you want affine mapping or not. But, it comes with many other helpful features as well!

If you notice any bugs, see where improvments can be made, or just want something added, feel free to shout it in the comments!

Also there is a version of the shader with extremely in-depth comments on it, that way anyone who wants to have a deep understanding of what is going on, can! Just let me know if you want it and I can provide it.

Fiending for more?

My digital-wizardry team and I will be dropping a demo for our movement-shooter-esq. game (with deck-building mechanics)! If that interests you, keep up with it through our’s and related sites: badskulljack, eneme, and (me) brainstinkalex.

P.S.: If you like the creepie-crawlie in the video, let 2nd Lieutenant Digital Wizard eneme know!

Shader code
shader_type spatial;
render_mode blend_mix,

varying float w_comp;

uniform float point_size : hint_range(0,128);
uniform float roughness : hint_range(0,1);
uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_enable;
uniform float specular;
uniform float metallic;
uniform sampler2D texture_emission : source_color, hint_default_black,filter_linear_mipmap,repeat_enable;
uniform vec4 emission : source_color;
uniform float emission_energy;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;

uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_enable;

uniform ivec2 resolution = ivec2(320, 240);
uniform bool affine_mapping = true;
uniform float alpha_scissor : hint_range(0, 1) = 0.5;
uniform float jitter: hint_range(0, 1) = 0.25;

void vertex()
	w_comp = (PROJECTION_MATRIX * vec4(VERTEX, 1.0)).w;
	VERTEX /= w_comp;
	vec2 grid_to_snap = vec2(resolution) * (1.0 - jitter);
	VERTEX.x = floor(VERTEX.x * grid_to_snap.x) / grid_to_snap.x;
	VERTEX.y = floor(VERTEX.y * grid_to_snap.y) / grid_to_snap.y;
	VERTEX *= w_comp;
	if(affine_mapping == true){
		UV *= w_comp;
	//IMPORTANT NOTE: Make sure `NORMAL`s are transformed out of local space aswell.
	NORMAL = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);

void fragment() {
	vec2 base_uv = UV;
	if(affine_mapping == true){
		base_uv /= w_comp;
	vec4 color_base = COLOR;
	vec4 texture_color = texture(texture_albedo, base_uv);
	ALBEDO = albedo.rgb * texture_color.rgb;
	ALPHA = texture_color.a * color_base.a;
	float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel);
	METALLIC = metallic_tex * metallic;
	vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0);
	float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel);
	ROUGHNESS = roughness_tex * roughness;
	SPECULAR = specular;
	vec3 emission_tex = texture(texture_emission,base_uv).rgb;
	EMISSION = (emission.rgb+emission_tex)*emission_energy;
Affine-Mapping, Jitter, ps1, psx, retro, Vector-Snapping
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

Procedural Window Rain Drop Shader

PSX Shader with Vertex Lighting

PSX Style Camera Shader – Distance Fog, Dithering, Color Limiter, Noise

Notify of

Newest Most Voted
Inline Feedbacks
View all comments
1 day ago

This is super cool, and I managed to rig it up to use ORM maps as all of my assets use them, but I can’t get Godot to automatically add the ORM map to the shader parameters the same way it does with the standalone maps and albedo. Any clues on that?