ChocolateBird/shaders/tilemap_shader.gdshader

44 lines
1.8 KiB
Plaintext
Raw Permalink Normal View History

2023-08-14 21:48:18 +09:30
shader_type canvas_item;
uniform sampler2D tile_atlas : hint_normal;
uniform sampler2D palette : hint_normal;
uniform float palette_rows = 8.0; // 128 colours
// uniform float tile_width = 8.0;
uniform vec2 tilemap_size = vec2(32.0, 20.0); // Battle tilemaps are 32x20, zone tilemaps are larger (64x64?)
const float INDEX_SCALE = 255.0 / 16.0;
// This shader maps from tileID texels to Tiles, and then applies 4bpp (16-colour) palette.
// tile_atlas hardcoded to 16x16 tiles for now
const float ATLAS_SIZE = 16.0;
// palette hardcoded to 16 columns of colors for now
void fragment() {
// GLES2
vec2 xy = UV * tilemap_size; // Texel-space coord of our texture
vec2 t = texture(TEXTURE, UV).ra;
int tile_idx = int(t.x * 255.0); // Luminosity channel (any RGB channel works)
int palette_idx = int(t.y * 255.0); // Alpha channel
// Extract flip bits from palette_idx byte
int v_flip = (palette_idx / 128);
palette_idx = palette_idx % 128;
int h_flip = (palette_idx / 64);
palette_idx = palette_idx % 64;
// Convert tile_idx to a texel coordinate, then to a UV coordinate
ivec2 tile_xy = ivec2(tile_idx%16, tile_idx/16);
vec2 tile_uv = vec2(tile_xy)/16.0;
// Get sub-tile UV
vec2 sub_tile_uv = fract(xy);
sub_tile_uv.x = mix(sub_tile_uv.x, 1.0 - sub_tile_uv.x, float(h_flip)); // Branchless mirroring, maybe test perf against branched version at some point
sub_tile_uv.y = mix(sub_tile_uv.y, 1.0 - sub_tile_uv.y, float(v_flip));
vec2 lut_uv = tile_uv + (sub_tile_uv/ATLAS_SIZE);
// TODO: move cycling palette to a sampler2DArray or sampler3D rather than rebinding
float color_id = texture(tile_atlas, lut_uv).r;
float color_idx16 = color_id * INDEX_SCALE;
float pal_col = fract(color_idx16);
float pal_row = float(palette_idx);
COLOR = texture(palette, vec2(pal_col, pal_row));
// COLOR.a = step(0.000001, color_idx16); // Branchless transparency
}