shader_type canvas_item; uniform sampler2D tile_atlas : hint_normal; uniform sampler2D palette : hint_normal; // uniform float tile_width = 8.0; uniform float tilemap_width = 512.0; // Require square tilemap for now const float index_scale = 255.0 / 16.0; // This shader maps from tileID texels to Tiles, and then applies palette. // tiles hardcoded to 16x16 tiles for now // palette hardcoded to 16x16 colors for now vec2 get_tile_atlas_uv(float tile_id, vec2 uv) { float tile_idx16 = tile_id * index_scale; // Rescale from [0.0, 1.0] to [0, 255] to [0, 15.9375 (15+15/16)] float tile_row = trunc(tile_idx16) / 16.0; float tile_col = fract(tile_idx16); vec2 tile_uv = vec2(tile_col, tile_row); // Convert 15.9375 to vec2(0.9375==15/16, (15)/16), this should result in integer coordinates in [0,15] scaled to [0,15/16] for UV vec2 sub_tile_uv = fract(uv * tilemap_width) / 16.0; // TODO: add sea HScroll, waterfall VScroll tile UV modulation return tile_uv + sub_tile_uv; // return sub_tile_uv + vec2(0.0, 0.5); } void fragment() { // GLES2 // vec2 uv_tile = trunc(UV * tilemap_width) / tilemap_width; vec2 uv_tile = UV; float s = texture(TEXTURE, uv_tile).r; // TODO: move cycling palette to a sampler2DArray or sampler3D rather than rebinding vec2 lut_uv = get_tile_atlas_uv(s, UV); float color_id = texture(tile_atlas, lut_uv).r; float color_idx16 = color_id * index_scale; float pal_row = trunc(color_idx16) / 16.0; float pal_col = fract(color_idx16); vec2 palette_uv = vec2(pal_col, pal_row); COLOR = texture(palette, palette_uv); COLOR.a = step(0.000001, color_idx16); // Branchless transparency }