Skip to content

Instantly share code, notes, and snippets.

@partybusiness
Last active November 14, 2024 19:57
Show Gist options
  • Save partybusiness/cd0f5a35c65f5b6ad637baff0dc6fe26 to your computer and use it in GitHub Desktop.
Save partybusiness/cd0f5a35c65f5b6ad637baff0dc6fe26 to your computer and use it in GitHub Desktop.
Displays square particles that round off their position to the nearest on-screen square and disaplays the computer text
shader_type spatial;
render_mode unshaded, depth_test_disabled;
// will need to assign this in code because I can't get Godot to save it as a property of material
uniform uint tilemap[1024]; // up to 128 8-byte 8x8 tiles
uniform int screenWidth = 168;
uniform int screenHeight = 64;
varying vec4 calcscreen; //calculated screen size and
uniform sampler2D depth_texture : source_color, hint_depth_texture, filter_nearest, repeat_disable;
//gets whether a pixel within a given tile is foreground or background
bool getPixel (uint x, uint y, uint tileIndex) { //x and y within 8x8 tile, index of tile in tilemap
uint tileAddress = (tileIndex << 3u); //8 bytes per tile
uint chunk = tilemap[tileAddress + y];
uint sample = chunk >> x & 1u;
return sample > 0u;
}
void vertex() {
// get position of vertex on screen
vec4 vert = vec4(VERTEX, 1.0);
vec4 screenPos = (PROJECTION_MATRIX * VIEW_MATRIX * MODEL_MATRIX * vec4(VERTEX, 1.0));
vec2 offset = vec2(0.5);
// flatten image and align from corner
screenPos.xy = screenPos.xy / screenPos.w + offset;
float sw = float(screenWidth)/2.0;//VIEWPORT_SIZE.x / round(VIEWPORT_SIZE.x/float(screenWidth))/2.0;
float sh = float(screenHeight)/2.0;//VIEWPORT_SIZE.y / round(VIEWPORT_SIZE.y/float(screenHeight))/2.0;
// round that position off to nearest square
screenPos.x = (round((screenPos.x) * sw) ) / sw;
screenPos.y = (round((screenPos.y) * sh) ) / sh;
// pass this along to fragment shader for depth sampling
calcscreen = vec4((screenPos.xy)+0.5, sw, sh);
// unflatten image and align from corner again
screenPos.xy = (screenPos.xy - offset) * screenPos.w;
POSITION = screenPos;
}
void fragment() {
float sw = calcscreen.z;
float sh = calcscreen.w;
//get current tile
uint tilex = uint(floor(calcscreen.x * sw));
uint tiley = uint(floor(calcscreen.y * sh));
vec2 flooredUV = vec2(float(tilex)/sw, float(tiley) / sh);
//get x and y pixel within current tile
vec2 tileUV = (calcscreen.xy - flooredUV) * vec2(sw, sh);
uint xindex = uint(floor(tileUV.x * 8.));
uint yindex = uint(floor(tileUV.y * 8.)); //max = 4294967295 //2147483648
// calculates index based on tile on-screen
// other ideas are get an index from particle ID or by sampling the screen_texture
uint index = ( tilex * 7u * tiley * 13u + tilex ) % 128u;
// this uses the byte array for pixel data
// I guess I could make a version that just uses a texture
bool ispixel = getPixel(xindex, yindex, index);
ALBEDO.rgb = vec3(0.0, ispixel?0.7:0.0, 0.0);
// sample depth
float depth = textureLod(depth_texture, (round(calcscreen.xy / 2.0 * vec2(sw, sh)) + vec2(0.5)) / vec2(sw, sh), 0.0).x;
vec3 ndc = vec3(calcscreen.xy * 2.0 - 1.0 + vec2(0.0, 0.1), depth); //assumes vulkan
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
view.xyz /= view.w;
float linear_depth = -view.z;
ALPHA = (-VERTEX.z > linear_depth)?0.0:1.0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment