Fixed world map rendering
This commit is contained in:
parent
36dc124edb
commit
058f436a7d
|
@ -34,9 +34,9 @@ I have mostly solved parsing of SNES menus in a sister project, however there ar
|
||||||
- [ ] Vehicle sprites (solved problem, soon™)
|
- [ ] Vehicle sprites (solved problem, soon™)
|
||||||
#### World Maps (Fields?)
|
#### World Maps (Fields?)
|
||||||
- [x] Tiles
|
- [x] Tiles
|
||||||
- [ ] Tilemaps (solved problem, soon™)
|
- [x] Tilemaps
|
||||||
- [ ] Dynamic changes (e.g. meteors, breaking seals, sinking island, pirate cave, voids) (might hardcode these later)
|
- [ ] Dynamic changes (e.g. meteors, breaking seals, sinking island, pirate cave, voids) (might hardcode these later)
|
||||||
- [ ] Pathing (I have vague recollections about this)
|
- [ ] Pathing (Data is in place, just needs moving around with collisions)
|
||||||
- [ ] Mode 7 Effects (...might hardcode these later)
|
- [ ] Mode 7 Effects (...might hardcode these later)
|
||||||
#### Dungeon/Town/Zone Maps (idk what accepted terminology is)
|
#### Dungeon/Town/Zone Maps (idk what accepted terminology is)
|
||||||
- [ ] Tiles (solved problem, soon™)
|
- [ ] Tiles (solved problem, soon™)
|
||||||
|
|
|
@ -89,7 +89,7 @@ class WorldMap:
|
||||||
data[y_off + x_off + 1] = self.block_tile_ids[tile_offset+1]
|
data[y_off + x_off + 1] = self.block_tile_ids[tile_offset+1]
|
||||||
data[y_off + tile_width + x_off] = self.block_tile_ids[tile_offset+2]
|
data[y_off + tile_width + x_off] = self.block_tile_ids[tile_offset+2]
|
||||||
data[y_off + tile_width + x_off + 1] = self.block_tile_ids[tile_offset+3]
|
data[y_off + tile_width + x_off + 1] = self.block_tile_ids[tile_offset+3]
|
||||||
image.create_from_data(tile_width, tile_height, false, Image.FORMAT_R8, data)
|
image.create_from_data(tile_width, tile_height, false, SpriteLoader.INDEX_FORMAT, data)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
var worldmaps = [WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new()]
|
var worldmaps = [WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new(), WorldMap.new()]
|
||||||
|
@ -135,6 +135,7 @@ func load_worldmaps(rom: File):
|
||||||
rom.seek(chunk_addresses[chunk_id])
|
rom.seek(chunk_addresses[chunk_id])
|
||||||
var chunk_size := 0
|
var chunk_size := 0
|
||||||
while chunk_size < 256:
|
while chunk_size < 256:
|
||||||
|
# var b: int = (blockmap.size() % 16) + (16 * (chunk_id % 12)); # For debugging the map shader against blocks
|
||||||
var b := rom.get_8()
|
var b := rom.get_8()
|
||||||
if b >= 0xC0: # RLE
|
if b >= 0xC0: # RLE
|
||||||
var count := b-0xBF
|
var count := b-0xBF
|
||||||
|
|
|
@ -2,6 +2,10 @@ extends Node
|
||||||
|
|
||||||
var shader_material = load('res://palette_mat.tres')
|
var shader_material = load('res://palette_mat.tres')
|
||||||
|
|
||||||
|
# Portability for GLES2 vs GLES3 stuff
|
||||||
|
const INDEX_FORMAT := Image.FORMAT_L8
|
||||||
|
|
||||||
|
|
||||||
# Offsets
|
# Offsets
|
||||||
|
|
||||||
# Glyphs
|
# Glyphs
|
||||||
|
@ -122,13 +126,13 @@ func gba_4bpp_to_tile(data: PoolByteArray) -> Image:
|
||||||
tdata[i*2] = data[i] % 16
|
tdata[i*2] = data[i] % 16
|
||||||
tdata[i*2+1] = data[i] / 16
|
tdata[i*2+1] = data[i] / 16
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, tdata)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, tdata)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_mode7_to_tile(data: PoolByteArray) -> Image:
|
func snes_mode7_to_tile(data: PoolByteArray) -> Image:
|
||||||
# Easy one, it's just straight data left-to-right, top-to-bottom
|
# Easy one, it's just straight data left-to-right, top-to-bottom
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, data)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, data)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_mode7_compressed_to_tile(data: PoolByteArray, tile_palette: int = 0) -> Image:
|
func snes_mode7_compressed_to_tile(data: PoolByteArray, tile_palette: int = 0) -> Image:
|
||||||
|
@ -148,7 +152,7 @@ func snes_4plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
var x = 7 - (i%8)
|
var x = 7 - (i%8)
|
||||||
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1) | ((data[j+16] >> x & 1)<<2) | ((data[j+17] >> x & 1)<<3)
|
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1) | ((data[j+16] >> x & 1)<<2) | ((data[j+17] >> x & 1)<<3)
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, tdata)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, tdata)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_3plane_to_tile(data: PoolByteArray) -> Image:
|
func snes_3plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
|
@ -158,7 +162,7 @@ func snes_3plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
var x = 7 - (i%8)
|
var x = 7 - (i%8)
|
||||||
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1) | ((data[(i/8)+16] >> x & 1)<<2)
|
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1) | ((data[(i/8)+16] >> x & 1)<<2)
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, tdata)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, tdata)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_2plane_to_tile(data: PoolByteArray) -> Image:
|
func snes_2plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
|
@ -168,7 +172,7 @@ func snes_2plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
var x = 7 - (i%8)
|
var x = 7 - (i%8)
|
||||||
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1)
|
tdata[i] = (data[j] >> x & 1) | ((data[j+1] >> x & 1)<<1)
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, tdata)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, tdata)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_1plane_to_tile(data: PoolByteArray) -> Image:
|
func snes_1plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
|
@ -177,7 +181,7 @@ func snes_1plane_to_tile(data: PoolByteArray) -> Image:
|
||||||
var x = 7 - (i%8)
|
var x = 7 - (i%8)
|
||||||
tdata[i] = (data[i/8] >> x & 1)
|
tdata[i] = (data[i/8] >> x & 1)
|
||||||
var tile := Image.new()
|
var tile := Image.new()
|
||||||
tile.create_from_data(8, 8, false, Image.FORMAT_R8, tdata)
|
tile.create_from_data(8, 8, false, INDEX_FORMAT, tdata)
|
||||||
return tile
|
return tile
|
||||||
|
|
||||||
func snes_get_tile(rom: File, offset: int, length: int) -> Image:
|
func snes_get_tile(rom: File, offset: int, length: int) -> Image:
|
||||||
|
@ -198,7 +202,7 @@ func snes_get_tile(rom: File, offset: int, length: int) -> Image:
|
||||||
func make_tile_atlas(tile_images) -> Image:
|
func make_tile_atlas(tile_images) -> Image:
|
||||||
var r := Rect2(0, 0, 8, 8)
|
var r := Rect2(0, 0, 8, 8)
|
||||||
var image = Image.new()
|
var image = Image.new()
|
||||||
image.create(128, 128, false, Image.FORMAT_R8)
|
image.create(128, 128, false, INDEX_FORMAT)
|
||||||
var tile = 0
|
var tile = 0
|
||||||
for y in tile_images.size()/16:
|
for y in tile_images.size()/16:
|
||||||
for x in 16:
|
for x in 16:
|
||||||
|
@ -240,7 +244,7 @@ func snes_load_worldmap(rom: File):
|
||||||
var block_tile_ids := PoolByteArray()
|
var block_tile_ids := PoolByteArray()
|
||||||
for block in 0xC0: # 192 blocks per world tileset
|
for block in 0xC0: # 192 blocks per world tileset
|
||||||
image = Image.new()
|
image = Image.new()
|
||||||
image.create(16, 16, false, Image.FORMAT_R8)
|
image.create(16, 16, false, INDEX_FORMAT)
|
||||||
for tile in 4:
|
for tile in 4:
|
||||||
rom.seek(block_bank_start + block + (tile * 0xC0)) # Horrible interleaving scheme
|
rom.seek(block_bank_start + block + (tile * 0xC0)) # Horrible interleaving scheme
|
||||||
var src_idx := rom.get_8()
|
var src_idx := rom.get_8()
|
||||||
|
@ -254,7 +258,7 @@ func snes_load_worldmap(rom: File):
|
||||||
worldmap_block_tile_ids.append(block_tile_ids)
|
worldmap_block_tile_ids.append(block_tile_ids)
|
||||||
# Make block atlas
|
# Make block atlas
|
||||||
image = Image.new()
|
image = Image.new()
|
||||||
image.create(16*16, 16*12, false, Image.FORMAT_R8)
|
image.create(16*16, 16*12, false, INDEX_FORMAT)
|
||||||
for block in 0xC0:
|
for block in 0xC0:
|
||||||
image.blit_rect(block_images[block], Rect2(0, 0, 16, 16), Vector2((block%16)*16, (block/16)*16))
|
image.blit_rect(block_images[block], Rect2(0, 0, 16, 16), Vector2((block%16)*16, (block/16)*16))
|
||||||
worldmap_block_atlas_imgs.append(image)
|
worldmap_block_atlas_imgs.append(image)
|
||||||
|
@ -262,7 +266,7 @@ func snes_load_worldmap(rom: File):
|
||||||
|
|
||||||
# # DEBUG: Make tile atlas
|
# # DEBUG: Make tile atlas
|
||||||
# image = Image.new()
|
# image = Image.new()
|
||||||
# image.create(16*8, (tile_count/16)*8, false, Image.FORMAT_R8)
|
# image.create(16*8, (tile_count/16)*8, false, INDEX_FORMAT)
|
||||||
# for tile in tile_count:
|
# for tile in tile_count:
|
||||||
# image.blit_rect(tile_images[tile], Rect2(0, 0, 8, 8), Vector2((tile%16)*8, (tile/16)*8))
|
# image.blit_rect(tile_images[tile], Rect2(0, 0, 8, 8), Vector2((tile%16)*8, (tile/16)*8))
|
||||||
# worldmap_tile_atlas_textures.append(texture_from_image(image))
|
# worldmap_tile_atlas_textures.append(texture_from_image(image))
|
||||||
|
@ -280,7 +284,7 @@ func load_snes_rom(rom: File):
|
||||||
for i in range(0, 32*48, 32):
|
for i in range(0, 32*48, 32):
|
||||||
tiles.append(snes_get_tile(rom, offset_Character_Battle_Sprite_Tiles + (strip*32*48) + i, 32))
|
tiles.append(snes_get_tile(rom, offset_Character_Battle_Sprite_Tiles + (strip*32*48) + i, 32))
|
||||||
var strip_image = Image.new()
|
var strip_image = Image.new()
|
||||||
strip_image.create(16, 24 * num_Character_Battle_Sprite_Layouts, false, Image.FORMAT_R8)
|
strip_image.create(16, 24 * num_Character_Battle_Sprite_Layouts, false, INDEX_FORMAT)
|
||||||
for i in range(6 * num_Character_Battle_Sprite_Layouts):
|
for i in range(6 * num_Character_Battle_Sprite_Layouts):
|
||||||
strip_image.blit_rect(tiles[battle_strip_layouts[i]], Rect2(0, 0, 8, 8), Vector2((i%2) * 8, (i/2) * 8))
|
strip_image.blit_rect(tiles[battle_strip_layouts[i]], Rect2(0, 0, 8, 8), Vector2((i%2) * 8, (i/2) * 8))
|
||||||
strip_images.append(strip_image)
|
strip_images.append(strip_image)
|
||||||
|
@ -334,7 +338,7 @@ func load_gba_rom(filename: String):
|
||||||
for i in range(8, 57*32+8, 32):
|
for i in range(8, 57*32+8, 32):
|
||||||
tiles.append(gba_4bpp_to_tile(tiledata.subarray(i, i+32)))
|
tiles.append(gba_4bpp_to_tile(tiledata.subarray(i, i+32)))
|
||||||
var strip_image = Image.new()
|
var strip_image = Image.new()
|
||||||
strip_image.create(16, 24 * num_Character_Battle_Sprite_Layouts, false, Image.FORMAT_R8)
|
strip_image.create(16, 24 * num_Character_Battle_Sprite_Layouts, false, INDEX_FORMAT)
|
||||||
for i in range(6 * num_Character_Battle_Sprite_Layouts):
|
for i in range(6 * num_Character_Battle_Sprite_Layouts):
|
||||||
strip_image.blit_rect(tiles[battle_strip_layouts[i]], Rect2(0, 0, 8, 8), Vector2((i%2) * 8, (i/2) * 8))
|
strip_image.blit_rect(tiles[battle_strip_layouts[i]], Rect2(0, 0, 8, 8), Vector2((i%2) * 8, (i/2) * 8))
|
||||||
strip_images.append(strip_image)
|
strip_images.append(strip_image)
|
||||||
|
|
|
@ -10,10 +10,9 @@ void fragment() {
|
||||||
if (color_idx == uint(0))
|
if (color_idx == uint(0))
|
||||||
COLOR.a = 0.0;*/
|
COLOR.a = 0.0;*/
|
||||||
// GLES2
|
// GLES2
|
||||||
float color_idx = texture(TEXTURE, UV).a * index_scale;
|
float color_idx16 = texture(TEXTURE, UV).r * index_scale;
|
||||||
float row = trunc(color_idx) / 16.0;
|
float row = trunc(color_idx16) / 16.0;
|
||||||
float col = fract(color_idx);
|
float col = fract(color_idx16);
|
||||||
COLOR = texture(palette, vec2(col, row));
|
COLOR = texture(palette, vec2(col, row));
|
||||||
if (color_idx == 0.0)
|
COLOR.a = step(0.000001, color_idx16); // Branchless transparency
|
||||||
COLOR.a = 0.0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,33 +15,28 @@ vec2 get_tile_atlas_uv(float tile_id, vec2 uv) {
|
||||||
float tile_row = trunc(tile_idx16) / 16.0;
|
float tile_row = trunc(tile_idx16) / 16.0;
|
||||||
float tile_col = fract(tile_idx16);
|
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 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);
|
vec2 sub_tile_uv = fract(uv * tilemap_width) / 16.0;
|
||||||
|
|
||||||
// TODO: add sea HScroll, waterfall VScroll tile UV modulation
|
// TODO: add sea HScroll, waterfall VScroll tile UV modulation
|
||||||
return tile_uv + (sub_tile_uv/16.0);
|
return tile_uv + sub_tile_uv;
|
||||||
|
// return sub_tile_uv + vec2(0.0, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fragment() {
|
void fragment() {
|
||||||
// GLES2
|
// GLES2
|
||||||
float s = texture(TEXTURE, UV).a;
|
// vec2 uv_tile = trunc(UV * tilemap_width) / tilemap_width;
|
||||||
// float tile_idx = texture(TEXTURE, UV).a * index_scale; // Rescale from [0.0, 1.0] to [0, 255] to [0, 15.9375 (15+15/16)]
|
vec2 uv_tile = UV;
|
||||||
// float tile_row = trunc(tile_idx) / 16.0;
|
float s = texture(TEXTURE, uv_tile).r;
|
||||||
// float tile_col = fract(tile_idx);
|
|
||||||
// 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 = vec2(0.5, 0.5); //fract(UV * tilemap_width);
|
|
||||||
|
|
||||||
// TODO: move cycling palette to a sampler2DArray or sampler3D rather than rebinding
|
// TODO: move cycling palette to a sampler2DArray or sampler3D rather than rebinding
|
||||||
|
|
||||||
vec2 lut_uv = get_tile_atlas_uv(s, UV);
|
vec2 lut_uv = get_tile_atlas_uv(s, UV);
|
||||||
// vec2 lut_uv = tile_uv;
|
float color_id = texture(tile_atlas, lut_uv).r;
|
||||||
float color_id = texture(tile_atlas, lut_uv).a;
|
|
||||||
float color_idx16 = color_id * index_scale;
|
float color_idx16 = color_id * index_scale;
|
||||||
float pal_row = trunc(color_idx16) / 16.0;
|
float pal_row = trunc(color_idx16) / 16.0;
|
||||||
float pal_col = fract(color_idx16);
|
float pal_col = fract(color_idx16);
|
||||||
vec2 palette_uv = vec2(pal_col, pal_row);
|
vec2 palette_uv = vec2(pal_col, pal_row);
|
||||||
COLOR = texture(palette, palette_uv);
|
COLOR = texture(palette, palette_uv);
|
||||||
|
|
||||||
// if (color_idx16 == 0.0)
|
COLOR.a = step(0.000001, color_idx16); // Branchless transparency
|
||||||
// COLOR.a = 0.0;
|
|
||||||
COLOR.a = 1.0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ func _create_worldmap_texrects() -> void:
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
# Only create this after MapLoader and SpriteLoader have loaded!
|
# Only create this after MapLoader and SpriteLoader have loaded!
|
||||||
_create_worldmap_texrects()
|
_create_worldmap_texrects()
|
||||||
|
# _create_palette_and_atlas_texrects()
|
||||||
|
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
shader = ExtResource( 1 )
|
shader = ExtResource( 1 )
|
||||||
shader_param/tilemap_width = 256.0
|
shader_param/tilemap_width = 512.0
|
||||||
|
|
Loading…
Reference in New Issue