Godot Version
4.2
Question
I’m adding PS1 style vertex snapping to my game. I have the following shader:
shader_type spatial;
uniform sampler2D albedo_texture : source_color;
uniform vec4 tint_color = vec4(1.0, 0.0, 0.0, 1.0); // Red tint
void vertex() {
// Adjust the snap intensity; higher values result in more noticeable snapping.
float snap_value = 1.0 / 120.0; // Adjust as needed
// Transform to clip space
vec4 clip_pos = PROJECTION_MATRIX * MODELVIEW_MATRIX * vec4(VERTEX, 1.0);
// Perspective division to NDC
vec3 ndc_pos = clip_pos.xyz / clip_pos.w;
// Snap in screen space
ndc_pos.xy = floor(ndc_pos.xy / snap_value + 0.5) * snap_value;
// Reconstruct clip space position
clip_pos.xyz = ndc_pos * clip_pos.w;
// Set the transformed position
POSITION = clip_pos;
}
void fragment() {
vec4 tex_color = texture(albedo_texture, UV);
ALBEDO = tex_color.rgb * tint_color.rgb;
ALPHA = tex_color.a;
}
And it’s applied from here:
extends Node
# Preload your custom snap shader
var snap_shader = preload("res://snap_shader.gdshader")
# Define texture flag constants
const FILTER_FLAG = 1 << 0 # 1
const MIPMAPS_FLAG = 1 << 1 # 2
# Add other flags if necessary
func _ready():
apply_snap_shader_to_tree(get_tree().get_root())
func apply_snap_shader_to_tree(node):
if node is MeshInstance3D:
# Get the currently active material
var existing_material = node.get_active_material(0)
if existing_material:
# Create a new ShaderMaterial
var shader_material = ShaderMaterial.new()
shader_material.shader = snap_shader
# Handle different material types
if existing_material is StandardMaterial3D:
# Duplicate and modify the albedo texture
var original_albedo = existing_material.albedo_texture
if original_albedo:
var albedo_dup = original_albedo.duplicate()
shader_material.set_shader_parameter("albedo_texture", albedo_dup)
# Duplicate and modify the normal texture if it exists
if existing_material.normal_texture:
var original_normal = existing_material.normal_texture
var normal_dup = original_normal.duplicate()
shader_material.set_shader_parameter("normal_texture", normal_dup)
# Copy the albedo color (tint color)
shader_material.set_shader_parameter("tint_color", existing_material.albedo_color)
elif existing_material is ShaderMaterial:
# Handle ShaderMaterial differently if needed
# For simplicity, you can skip or merge shaders if needed
pass
else:
# Handle other material types if necessary
pass
# Apply the new shader material as a material override
node.material_override = shader_material
# Recursively apply to all child nodes
for child in node.get_children():
apply_snap_shader_to_tree(child)
ChatGPT helped with a lot of this…
Anyway, it looks really nice, but textures are now blurry. I want them to have nearest neighbour pixellation. I can’t find a way to do this. ChatGPT has given me a million variations of code re flags
, which don’t seem to be a thing in 4.2. Any help is massively appreciated!