Ok, I'm back.
I did try to render everything in lower res, it did have a nice effect, but it did not solve the problem. Also I need it in a shader because I want to do things like lock the pixels to a color palette and maybe change the resolution as zoom changes etc.
That shader is pretty interesting, it still runs when moving in the diagonal though. After some thought I realise it's probably related to the fact that mo original shader did not adjust for aspect ratio. I fixed mine for aspect ratio and had similar results.
Anyway, I sat this whole weekend experimenting with different things and managed to get the shaders (almost ) rock solid with a orthographic camera using this shader, I'll let the comments do the explaining:
shader_type canvas_item;
//All uniforms fed from script
uniform bool grid = false;
uniform vec2 pos = vec2(0,0); //Camera position divided by ortho camera size, adjusted for cam rotation
uniform float aspect_ratio = 1f; // X base, used to adjust pixel grid for aspect ratio
uniform float pixel_clamp = 0.7; //Pixel grid step
void fragment()
{
float x = pixel_clamp / aspect_ratio; //Adjust pixel grid for aspect ratio
float y = pixel_clamp;
//Calculate camera offset from pixel grid
vec2 offset = mod(vec2(pos.x/aspect_ratio, pos.y), vec2(x,y));
vec2 uv = SCREEN_UV;
//Snap UV to grid intersects, has pixelation effect
uv -= mod(uv,vec2(x,y));
//Offset UV, has effect of snapping camera to pixel grid
uv.y += offset.y;
uv.x -= offset.x;
COLOR = textureLod(SCREEN_TEXTURE,uv,0);
This is the script feeding the uniforms:
extends ColorRect
var screen_size
var cam_perspective
var ortho_cam
var rot_adjustment
func _ready():
ortho_cam = get_tree().get_root().get_node("Spatial/Orthogonal")
rot_adjustment = Vector2(sin(PI/2-ortho_cam.rotation.y),cos(-PI/2-ortho_cam.rotation.x)) #Adjust shader input for ortho camera rotation
func _process(delta):
#Set color rect size to cover screen
margin_right = get_viewport_rect().size.x
margin_bottom = get_viewport_rect().size.y
screen_size = get_viewport_rect().size
get_material().set_shader_param("pos", Vector2(cam_perspective.translation.x, cam_perspective.translation.z)*rot_adjustment/ortho_cam.size)
get_material().set_shader_param("aspect_ratio", screen_size.x/screen_size.y)
As you can probably see, the rotations(rot_adjustment) won't work if there are rotations in multiple axes. But I'm a bit of a noob with 3D so I just did this as a quick fix.
So this will make the pixels(mostly) solid, but as one might imagine as pixel size increases the snapping becomes more noticeable. Now if I this could be achieved without the snapping effect that would be great. Also I actually need to do this in perspective, so that's gonna be fun to try and figure out...