Automatic texture atlas generation from terrain.png

cannot use terrain.png directly due to texture bleeding
This commit is contained in:
xtreme8000 2023-04-21 18:30:46 +02:00
parent c9719c5077
commit ca295db3c7
67 changed files with 1204 additions and 302 deletions

View file

@ -102,12 +102,14 @@ add_executable(cavex
source/graphics/gui_util.c
source/graphics/render_block.c
source/graphics/render_item.c
source/graphics/texture_atlas.c
source/platform/displaylist.c
source/platform/gfx.c
source/platform/input.c
source/platform/thread.c
source/platform/time.c
source/platform/texture.c
source/chunk_mesher.c
source/chunk.c

View file

@ -23,7 +23,7 @@ include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source source/block source/graphics source/network source/game source/game/gui source/platform source/item source/cNBT
SOURCES := source source/block source/graphics source/network source/game source/game/gui source/platform source/item source/cNBT source/lodepng
DATA :=
TEXTURES := textures
INCLUDES :=

View file

@ -47,29 +47,33 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
if(this->block->metadata & 0x8) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(7, 8);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_BED_TOP_2);
case SIDE_LEFT:
case SIDE_RIGHT:
return (this->block->metadata & 0x1) ? TEXTURE_INDEX(11, 8) :
TEXTURE_INDEX(10, 8);
return (this->block->metadata & 0x1) ?
tex_atlas_lookup(TEXAT_BED_FRONT) :
tex_atlas_lookup(TEXAT_BED_SIDE_2);
case SIDE_FRONT:
case SIDE_BACK:
return (this->block->metadata & 0x1) ? TEXTURE_INDEX(10, 8) :
TEXTURE_INDEX(11, 8);
default: return TEXTURE_INDEX(4, 0);
return (this->block->metadata & 0x1) ?
tex_atlas_lookup(TEXAT_BED_SIDE_2) :
tex_atlas_lookup(TEXAT_BED_FRONT);
default: return tex_atlas_lookup(TEXAT_PLANKS);
}
} else {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(6, 8);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_BED_TOP_1);
case SIDE_LEFT:
case SIDE_RIGHT:
return (this->block->metadata & 0x1) ? TEXTURE_INDEX(8, 8) :
TEXTURE_INDEX(9, 8);
return (this->block->metadata & 0x1) ?
tex_atlas_lookup(TEXAT_BED_BACK) :
tex_atlas_lookup(TEXAT_BED_SIDE_1);
case SIDE_FRONT:
case SIDE_BACK:
return (this->block->metadata & 0x1) ? TEXTURE_INDEX(9, 8) :
TEXTURE_INDEX(8, 8);
default: return TEXTURE_INDEX(4, 0);
return (this->block->metadata & 0x1) ?
tex_atlas_lookup(TEXAT_BED_SIDE_1) :
tex_atlas_lookup(TEXAT_BED_BACK);
default: return tex_atlas_lookup(TEXAT_PLANKS);
}
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, 1);
return tex_atlas_lookup(TEXAT_BEDROCK);
}
struct block block_bedrock = {

View file

@ -37,8 +37,8 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(4, 0);
default: return TEXTURE_INDEX(3, 2);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_PLANKS);
default: return tex_atlas_lookup(TEXAT_BOOKSHELF);
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(7, 0);
return tex_atlas_lookup(TEXAT_BRICKS);
}
struct block block_bricks = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(13, 1);
return tex_atlas_lookup(TEXAT_MUSHROOM_BROWN);
}
struct block block_brown_mushroom = {

View file

@ -45,9 +45,9 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(5, 4);
case SIDE_BOTTOM: return TEXTURE_INDEX(7, 4);
default: return TEXTURE_INDEX(6, 4);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_CACTUS_TOP);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CACTUS_BOTTOM);
default: return tex_atlas_lookup(TEXAT_CACTUS_SIDE);
}
}

View file

@ -46,12 +46,13 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(9, 7);
case SIDE_BOTTOM: return TEXTURE_INDEX(12, 7);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_CAKE_TOP);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CAKE_BOTTOM);
case SIDE_LEFT:
return (this->block->metadata > 0) ? TEXTURE_INDEX(11, 7) :
TEXTURE_INDEX(10, 7);
default: return TEXTURE_INDEX(10, 7);
return (this->block->metadata > 0) ?
tex_atlas_lookup(TEXAT_CAKE_SIDE_CUT) :
tex_atlas_lookup(TEXAT_CAKE_SIDE);
default: return tex_atlas_lookup(TEXAT_CAKE_SIDE);
}
}

View file

@ -35,19 +35,19 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(6, 1);
return tex_atlas_lookup(TEXAT_CAST_BLOCK_IRON);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(7, 1);
return tex_atlas_lookup(TEXAT_CAST_BLOCK_GOLD);
}
static uint8_t getTextureIndex3(struct block_info* this, enum side side) {
return TEXTURE_INDEX(8, 1);
return tex_atlas_lookup(TEXAT_CAST_BLOCK_DIAMOND);
}
static uint8_t getTextureIndex4(struct block_info* this, enum side side) {
return TEXTURE_INDEX(0, 9);
return tex_atlas_lookup(TEXAT_CAST_BLOCK_LAPIS);
}
struct block block_iron = {

View file

@ -45,59 +45,62 @@ static uint8_t getTextureIndex(struct block_info* this, enum side side) {
if(right->type == this->block->type) {
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1);
case SIDE_BACK: return TEXTURE_INDEX(9, 2);
case SIDE_FRONT: return TEXTURE_INDEX(10, 3);
default: return TEXTURE_INDEX(10, 1);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CHEST_TOP);
case SIDE_BACK: return tex_atlas_lookup(TEXAT_CHEST_FRONT_1);
case SIDE_FRONT: return tex_atlas_lookup(TEXAT_CHEST_BACK_2);
default: return tex_atlas_lookup(TEXAT_CHEST_SIDE);
}
}
if(left->type == this->block->type) {
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1);
case SIDE_BACK: return TEXTURE_INDEX(10, 2);
case SIDE_FRONT: return TEXTURE_INDEX(9, 3);
default: return TEXTURE_INDEX(10, 1);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CHEST_TOP);
case SIDE_BACK: return tex_atlas_lookup(TEXAT_CHEST_FRONT_2);
case SIDE_FRONT: return tex_atlas_lookup(TEXAT_CHEST_BACK_1);
default: return tex_atlas_lookup(TEXAT_CHEST_SIDE);
}
}
if(back->type == this->block->type) {
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1);
case SIDE_RIGHT: return TEXTURE_INDEX(10, 2);
case SIDE_LEFT: return TEXTURE_INDEX(9, 3);
default: return TEXTURE_INDEX(10, 1);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CHEST_TOP);
case SIDE_RIGHT: return tex_atlas_lookup(TEXAT_CHEST_FRONT_2);
case SIDE_LEFT: return tex_atlas_lookup(TEXAT_CHEST_BACK_1);
default: return tex_atlas_lookup(TEXAT_CHEST_SIDE);
}
}
if(front->type == this->block->type) {
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(9, 1);
case SIDE_RIGHT: return TEXTURE_INDEX(9, 2);
case SIDE_LEFT: return TEXTURE_INDEX(10, 3);
default: return TEXTURE_INDEX(10, 1);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_CHEST_TOP);
case SIDE_RIGHT: return tex_atlas_lookup(TEXAT_CHEST_FRONT_1);
case SIDE_LEFT: return tex_atlas_lookup(TEXAT_CHEST_BACK_2);
default: return tex_atlas_lookup(TEXAT_CHEST_SIDE);
}
}
uint8_t tex[SIDE_MAX] = {
[SIDE_TOP] = TEXTURE_INDEX(9, 1), [SIDE_BOTTOM] = TEXTURE_INDEX(9, 1),
[SIDE_BACK] = TEXTURE_INDEX(10, 1), [SIDE_FRONT] = TEXTURE_INDEX(10, 1),
[SIDE_LEFT] = TEXTURE_INDEX(10, 1), [SIDE_RIGHT] = TEXTURE_INDEX(10, 1),
[SIDE_TOP] = tex_atlas_lookup(TEXAT_CHEST_TOP),
[SIDE_BOTTOM] = tex_atlas_lookup(TEXAT_CHEST_TOP),
[SIDE_BACK] = tex_atlas_lookup(TEXAT_CHEST_SIDE),
[SIDE_FRONT] = tex_atlas_lookup(TEXAT_CHEST_SIDE),
[SIDE_LEFT] = tex_atlas_lookup(TEXAT_CHEST_SIDE),
[SIDE_RIGHT] = tex_atlas_lookup(TEXAT_CHEST_SIDE),
};
if(left->type && !right->type)
tex[SIDE_RIGHT] = TEXTURE_INDEX(11, 1);
tex[SIDE_RIGHT] = tex_atlas_lookup(TEXAT_CHEST_FRONT_SINGLE);
else if(right->type && !left->type)
tex[SIDE_LEFT] = TEXTURE_INDEX(11, 1);
tex[SIDE_LEFT] = tex_atlas_lookup(TEXAT_CHEST_FRONT_SINGLE);
else if(front->type && !back->type)
tex[SIDE_BACK] = TEXTURE_INDEX(11, 1);
tex[SIDE_BACK] = tex_atlas_lookup(TEXAT_CHEST_FRONT_SINGLE);
else if(back->type && !front->type)
tex[SIDE_FRONT] = TEXTURE_INDEX(11, 1);
tex[SIDE_FRONT] = tex_atlas_lookup(TEXAT_CHEST_FRONT_SINGLE);
else
tex[SIDE_BACK] = TEXTURE_INDEX(11, 1);
tex[SIDE_BACK] = tex_atlas_lookup(TEXAT_CHEST_FRONT_SINGLE);
return tex[side];
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(8, 4);
return tex_atlas_lookup(TEXAT_CLAY);
}
struct block block_clay = {

View file

@ -36,8 +36,8 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(this->block->type) {
default: return TEXTURE_INDEX(0, 1);
case 48: return TEXTURE_INDEX(4, 2);
default: return tex_atlas_lookup(TEXAT_COBBLESTONE);
case 48: return tex_atlas_lookup(TEXAT_COBBLESTONE_MOSSY);
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(11, 0);
return tex_atlas_lookup(TEXAT_COBWEB);
}
struct block block_cobweb = {

View file

@ -35,7 +35,17 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(this->block->metadata + 6, 5);
switch(this->block->metadata) {
case 0: return tex_atlas_lookup(TEXAT_CROPS_0);
case 1: return tex_atlas_lookup(TEXAT_CROPS_1);
case 2: return tex_atlas_lookup(TEXAT_CROPS_2);
case 3: return tex_atlas_lookup(TEXAT_CROPS_3);
case 4: return tex_atlas_lookup(TEXAT_CROPS_4);
case 5: return tex_atlas_lookup(TEXAT_CROPS_5);
case 6: return tex_atlas_lookup(TEXAT_CROPS_6);
default:
case 7: return tex_atlas_lookup(TEXAT_CROPS_7);
}
}
struct block block_crops = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(2, 0);
return tex_atlas_lookup(TEXAT_DIRT);
}
struct block block_dirt = {

View file

@ -38,25 +38,25 @@ static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
if(this->block->metadata == 2)
return TEXTURE_INDEX(12, 4);
return tex_atlas_lookup(TEXAT_DISPENSER_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_BACK:
if(this->block->metadata == 3)
return TEXTURE_INDEX(12, 4);
return tex_atlas_lookup(TEXAT_DISPENSER_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_RIGHT:
if(this->block->metadata == 5)
return TEXTURE_INDEX(12, 4);
return tex_atlas_lookup(TEXAT_DISPENSER_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_LEFT:
if(this->block->metadata == 4)
return TEXTURE_INDEX(12, 4);
return tex_atlas_lookup(TEXAT_DISPENSER_FRONT);
else
return TEXTURE_INDEX(13, 2);
default: return TEXTURE_INDEX(13, 4);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
default: return tex_atlas_lookup(TEXAT_FURNACE_TOP);
}
}

View file

@ -61,11 +61,15 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, (this->block->metadata & 0x08) ? 5 : 6);
return (this->block->metadata & 0x08) ?
tex_atlas_lookup(TEXAT_DOOR_WOOD_TOP) :
tex_atlas_lookup(TEXAT_DOOR_WOOD_BOTTOM);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(2, (this->block->metadata & 0x08) ? 5 : 6);
return (this->block->metadata & 0x08) ?
tex_atlas_lookup(TEXAT_DOOR_IRON_TOP) :
tex_atlas_lookup(TEXAT_DOOR_IRON_BOTTOM);
}
struct block block_wooden_door = {

View file

@ -39,15 +39,16 @@ static uint8_t getTextureIndex(struct block_info* this, enum side side) {
default:
case 0:
return (side == SIDE_TOP || side == SIDE_BOTTOM) ?
TEXTURE_INDEX(6, 0) :
TEXTURE_INDEX(5, 0);
tex_atlas_lookup(TEXAT_SLAB_STONE_TOP) :
tex_atlas_lookup(TEXAT_SLAB_STONE_SIDE);
case 1:
return (side == SIDE_TOP) ?
TEXTURE_INDEX(0, 11) :
((side == SIDE_BOTTOM) ? TEXTURE_INDEX(0, 13) :
TEXTURE_INDEX(0, 12));
case 2: return TEXTURE_INDEX(4, 0);
case 3: return TEXTURE_INDEX(0, 1);
tex_atlas_lookup(TEXAT_SANDSTONE_TOP) :
((side == SIDE_BOTTOM) ?
tex_atlas_lookup(TEXAT_SANDSTONE_BOTTOM) :
tex_atlas_lookup(TEXAT_SANDSTONE_SIDE));
case 2: return tex_atlas_lookup(TEXAT_PLANKS);
case 3: return tex_atlas_lookup(TEXAT_COBBLESTONE);
}
}

View file

@ -41,9 +41,10 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP:
return (this->block->metadata < 7) ? TEXTURE_INDEX(5, 5) :
TEXTURE_INDEX(4, 5);
default: return TEXTURE_INDEX(2, 0);
return (this->block->metadata < 7) ?
tex_atlas_lookup(TEXAT_FARMLAND_DRY) :
tex_atlas_lookup(TEXAT_FARMLAND_WET);
default: return tex_atlas_lookup(TEXAT_DIRT);
}
}

View file

@ -44,7 +44,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(4, 0);
return tex_atlas_lookup(TEXAT_PLANKS);
}
struct block block_fence = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(13, 0);
return tex_atlas_lookup(TEXAT_DANDELION);
}
struct block block_flower = {

View file

@ -34,29 +34,55 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
return face_occlusion_full();
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
if(this->block->metadata == 2)
return TEXTURE_INDEX(12, 2);
return tex_atlas_lookup(TEXAT_FURNACE_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_BACK:
if(this->block->metadata == 3)
return TEXTURE_INDEX(12, 2);
return tex_atlas_lookup(TEXAT_FURNACE_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_RIGHT:
if(this->block->metadata == 5)
return TEXTURE_INDEX(12, 2);
return tex_atlas_lookup(TEXAT_FURNACE_FRONT);
else
return TEXTURE_INDEX(13, 2);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_LEFT:
if(this->block->metadata == 4)
return TEXTURE_INDEX(12, 2);
return tex_atlas_lookup(TEXAT_FURNACE_FRONT);
else
return TEXTURE_INDEX(13, 2);
default: return TEXTURE_INDEX(13, 4);
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
default: return tex_atlas_lookup(TEXAT_FURNACE_TOP);
}
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
if(this->block->metadata == 2)
return tex_atlas_lookup(TEXAT_FURNACE_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_BACK:
if(this->block->metadata == 3)
return tex_atlas_lookup(TEXAT_FURNACE_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_RIGHT:
if(this->block->metadata == 5)
return tex_atlas_lookup(TEXAT_FURNACE_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
case SIDE_LEFT:
if(this->block->metadata == 4)
return tex_atlas_lookup(TEXAT_FURNACE_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_FURNACE_SIDE);
default: return tex_atlas_lookup(TEXAT_FURNACE_TOP);
}
}
@ -65,7 +91,7 @@ struct block block_furnaceoff = {
.getSideMask = getSideMask,
.getBoundingBox = getBoundingBox,
.getMaterial = getMaterial,
.getTextureIndex = getTextureIndex,
.getTextureIndex = getTextureIndex1,
.transparent = false,
.renderBlock = render_block_full,
.renderBlockAlways = NULL,
@ -89,7 +115,7 @@ struct block block_furnaceon = {
.getSideMask = getSideMask,
.getBoundingBox = getBoundingBox,
.getMaterial = getMaterial,
.getTextureIndex = getTextureIndex,
.getTextureIndex = getTextureIndex2,
.transparent = false,
.renderBlock = render_block_full,
.renderBlockAlways = NULL,

View file

@ -36,7 +36,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, 3);
return tex_atlas_lookup(TEXAT_GLASS);
}
struct block block_glass = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(9, 6);
return tex_atlas_lookup(TEXAT_GLOWSTONE);
}
struct block block_glowstone = {

View file

@ -38,13 +38,13 @@ static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP:
return (this->neighbours[SIDE_TOP].type == BLOCK_SNOW) ?
TEXTURE_INDEX(2, 4) :
TEXTURE_INDEX(5, 9);
case SIDE_BOTTOM: return TEXTURE_INDEX(2, 0);
tex_atlas_lookup(TEXAT_SNOW) :
tex_atlas_lookup(TEXAT_GRASS_TOP);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_DIRT);
default:
return (this->neighbours[SIDE_TOP].type == BLOCK_SNOW) ?
TEXTURE_INDEX(4, 4) :
TEXTURE_INDEX(5, 10);
tex_atlas_lookup(TEXAT_GRASS_SIDE_SNOW) :
tex_atlas_lookup(TEXAT_GRASS_SIDE);
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(3, 1);
return tex_atlas_lookup(TEXAT_GRAVEL);
}
struct block block_gravel = {

View file

@ -36,8 +36,8 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(11, 4);
default: return TEXTURE_INDEX(10, 4);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_JUKBEBOX_TOP);
default: return tex_atlas_lookup(TEXAT_JUKBEBOX_SIDE);
}
}

View file

@ -52,7 +52,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(3, 5);
return tex_atlas_lookup(TEXAT_LADDER);
}
struct block block_ladder = {

View file

@ -45,9 +45,9 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(this->block->metadata & 0x3) {
case 1: return TEXTURE_INDEX(4, 8);
case 2: return TEXTURE_INDEX(4, 3);
default: return TEXTURE_INDEX(5, 11);
case 1: return tex_atlas_lookup(TEXAT_LEAVES_SPRUCE);
case 2: return tex_atlas_lookup(TEXAT_LEAVES_BIRCH);
default: return tex_atlas_lookup(TEXAT_LEAVES_OAK);
}
}

View file

@ -35,29 +35,14 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
if(side == SIDE_TOP || side == SIDE_BOTTOM)
return tex_atlas_lookup(TEXAT_LOG_OAK_TOP);
switch(this->block->metadata) {
default:
case 0:
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1);
default: return TEXTURE_INDEX(4, 1);
}
break;
case 1:
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1);
default: return TEXTURE_INDEX(4, 7);
}
break;
case 2:
switch(side) {
case SIDE_TOP:
case SIDE_BOTTOM: return TEXTURE_INDEX(5, 1);
default: return TEXTURE_INDEX(5, 7);
}
break;
case 0: return tex_atlas_lookup(TEXAT_LOG_OAK_SIDE);
case 1: return tex_atlas_lookup(TEXAT_LOG_SPRUCE_SIDE);
case 2: return tex_atlas_lookup(TEXAT_LOG_BIRCH_SIDE);
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(7, 6);
return tex_atlas_lookup(TEXAT_NETHERRACK);
}
struct block block_netherrack = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(10, 4);
return tex_atlas_lookup(TEXAT_JUKBEBOX_SIDE);
}
struct block block_noteblock = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(5, 2);
return tex_atlas_lookup(TEXAT_OBSIDIAN);
}
struct block block_obsidian = {

View file

@ -37,18 +37,18 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(this->block->type) {
case 14: // gold
return TEXTURE_INDEX(0, 2);
return tex_atlas_lookup(TEXAT_ORE_GOLD);
case 15: // iron
return TEXTURE_INDEX(1, 2);
return tex_atlas_lookup(TEXAT_ORE_IRON);
case 16: // coal
return TEXTURE_INDEX(2, 2);
return tex_atlas_lookup(TEXAT_ORE_COAL);
case 21: // lapis
return TEXTURE_INDEX(0, 10);
return tex_atlas_lookup(TEXAT_ORE_LAPIS);
case 56: // diamond
return TEXTURE_INDEX(2, 3);
return tex_atlas_lookup(TEXAT_ORE_DIAMOND);
case 73: // redstone
case 74: return TEXTURE_INDEX(3, 3);
default: return TEXTURE_INDEX(1, 0);
case 74: return tex_atlas_lookup(TEXAT_ORE_REDSTONE);
default: return tex_atlas_lookup(TEXAT_STONE);
}
}

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(4, 0);
return tex_atlas_lookup(TEXAT_PLANKS);
}
struct block block_planks = {

View file

@ -44,11 +44,11 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, 0);
return tex_atlas_lookup(TEXAT_STONE);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(4, 0);
return tex_atlas_lookup(TEXAT_PLANKS);
}
struct block block_stone_pressure_plate = {

View file

@ -34,29 +34,55 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
return face_occlusion_full();
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
if(this->block->metadata == 2)
return TEXTURE_INDEX(7, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT);
else
return TEXTURE_INDEX(6, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_BACK:
if(this->block->metadata == 0)
return TEXTURE_INDEX(7, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT);
else
return TEXTURE_INDEX(6, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_RIGHT:
if(this->block->metadata == 3)
return TEXTURE_INDEX(7, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT);
else
return TEXTURE_INDEX(6, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_LEFT:
if(this->block->metadata == 1)
return TEXTURE_INDEX(7, 7);
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT);
else
return TEXTURE_INDEX(6, 7);
default: return TEXTURE_INDEX(6, 6);
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
default: return tex_atlas_lookup(TEXAT_PUMPKIN_TOP);
}
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
if(this->block->metadata == 2)
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_BACK:
if(this->block->metadata == 0)
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_RIGHT:
if(this->block->metadata == 3)
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
case SIDE_LEFT:
if(this->block->metadata == 1)
return tex_atlas_lookup(TEXAT_PUMPKIN_FRONT_LIT);
else
return tex_atlas_lookup(TEXAT_PUMPKIN_SIDE);
default: return tex_atlas_lookup(TEXAT_PUMPKIN_TOP);
}
}
@ -65,7 +91,7 @@ struct block block_pumpkin = {
.getSideMask = getSideMask,
.getBoundingBox = getBoundingBox,
.getMaterial = getMaterial,
.getTextureIndex = getTextureIndex,
.getTextureIndex = getTextureIndex1,
.transparent = false,
.renderBlock = render_block_full,
.renderBlockAlways = NULL,
@ -89,7 +115,7 @@ struct block block_pumpkin_lit = {
.getSideMask = getSideMask,
.getBoundingBox = getBoundingBox,
.getMaterial = getMaterial,
.getTextureIndex = getTextureIndex,
.getTextureIndex = getTextureIndex2,
.transparent = false,
.renderBlock = render_block_full,
.renderBlockAlways = NULL,

View file

@ -40,17 +40,18 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return (this->block->metadata < 6) ? TEXTURE_INDEX(0, 8) :
TEXTURE_INDEX(0, 7);
return (this->block->metadata < 6) ? tex_atlas_lookup(TEXAT_RAIL) :
tex_atlas_lookup(TEXAT_RAIL_CURVED);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return (this->block->metadata & 0x8) ? TEXTURE_INDEX(3, 11) :
TEXTURE_INDEX(3, 10);
return (this->block->metadata & 0x8) ?
tex_atlas_lookup(TEXAT_RAIL_POWERED_ON) :
tex_atlas_lookup(TEXAT_RAIL_POWERED_OFF);
}
static uint8_t getTextureIndex3(struct block_info* this, enum side side) {
return TEXTURE_INDEX(3, 12);
return tex_atlas_lookup(TEXAT_RAIL_DETECTOR);
}
struct block block_rail = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(12, 1);
return tex_atlas_lookup(TEXAT_MUSHROOM_RED);
}
struct block block_red_mushroom = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(9, 4);
return tex_atlas_lookup(TEXAT_REED);
}
struct block block_reed = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(12, 0);
return tex_atlas_lookup(TEXAT_ROSE);
}
struct block block_rose = {

View file

@ -35,11 +35,11 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(2, 1);
return tex_atlas_lookup(TEXAT_SAND);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(8, 6);
return tex_atlas_lookup(TEXAT_SOULSAND);
}
struct block block_sand = {

View file

@ -36,9 +36,9 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(0, 11);
case SIDE_BOTTOM: return TEXTURE_INDEX(0, 13);
default: return TEXTURE_INDEX(0, 12);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_SANDSTONE_TOP);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_SANDSTONE_BOTTOM);
default: return tex_atlas_lookup(TEXAT_SANDSTONE_SIDE);
}
}

View file

@ -36,9 +36,9 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(this->block->metadata) {
case 1: return TEXTURE_INDEX(7, 2);
case 2: return TEXTURE_INDEX(8, 2);
default: return TEXTURE_INDEX(6, 2);
case 1: return tex_atlas_lookup(TEXAT_SAPLING_SPRUCE);
case 2: return tex_atlas_lookup(TEXAT_SAPLING_BIRCH);
default: return tex_atlas_lookup(TEXAT_SAPLING_OAK);
}
}

View file

@ -43,15 +43,16 @@ static uint8_t getTextureIndex(struct block_info* this, enum side side) {
default:
case 0:
return (side == SIDE_TOP || side == SIDE_BOTTOM) ?
TEXTURE_INDEX(6, 0) :
TEXTURE_INDEX(5, 0);
tex_atlas_lookup(TEXAT_SLAB_STONE_TOP) :
tex_atlas_lookup(TEXAT_SLAB_STONE_SIDE);
case 1:
return (side == SIDE_TOP) ?
TEXTURE_INDEX(0, 11) :
((side == SIDE_BOTTOM) ? TEXTURE_INDEX(0, 13) :
TEXTURE_INDEX(0, 12));
case 2: return TEXTURE_INDEX(4, 0);
case 3: return TEXTURE_INDEX(0, 1);
tex_atlas_lookup(TEXAT_SANDSTONE_TOP) :
((side == SIDE_BOTTOM) ?
tex_atlas_lookup(TEXAT_SANDSTONE_BOTTOM) :
tex_atlas_lookup(TEXAT_SANDSTONE_SIDE));
case 2: return tex_atlas_lookup(TEXAT_PLANKS);
case 3: return tex_atlas_lookup(TEXAT_COBBLESTONE);
}
}

View file

@ -50,7 +50,7 @@ getSideMask2(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(2, 4);
return tex_atlas_lookup(TEXAT_SNOW);
}
struct block block_snow = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, 4);
return tex_atlas_lookup(TEXAT_SPAWNER);
}
struct block block_spawner = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(0, 3);
return tex_atlas_lookup(TEXAT_SPONGE);
}
struct block block_sponge = {

View file

@ -98,11 +98,11 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(4, 0);
return tex_atlas_lookup(TEXAT_PLANKS);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(0, 1);
return tex_atlas_lookup(TEXAT_COBBLESTONE);
}
struct block block_wooden_stairs = {

View file

@ -35,7 +35,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(1, 0);
return tex_atlas_lookup(TEXAT_STONE);
}
struct block block_stone = {

View file

@ -36,14 +36,14 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
switch(this->block->metadata) {
case 1: return TEXTURE_INDEX(5, 12); // tallgrass
case 2: return TEXTURE_INDEX(5, 13); // fern
default: return TEXTURE_INDEX(6, 3); // deadbush
case 1: return tex_atlas_lookup(TEXAT_TALLGRASS); // tallgrass
case 2: return tex_atlas_lookup(TEXAT_FERN); // fern
default: return tex_atlas_lookup(TEXAT_DEADBUSH); // deadbush
}
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(6, 3); // deadbush
return tex_atlas_lookup(TEXAT_DEADBUSH); // deadbush
}
struct block block_tallgrass = {

View file

@ -36,9 +36,9 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_TOP: return TEXTURE_INDEX(9, 0);
case SIDE_BOTTOM: return TEXTURE_INDEX(10, 0);
default: return TEXTURE_INDEX(8, 0);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_TNT_TOP);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_TNT_BOTTOM);
default: return tex_atlas_lookup(TEXAT_TNT_SIDE);
}
}

View file

@ -44,15 +44,15 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex1(struct block_info* this, enum side side) {
return TEXTURE_INDEX(0, 5);
return tex_atlas_lookup(TEXAT_TORCH);
}
static uint8_t getTextureIndex2(struct block_info* this, enum side side) {
return TEXTURE_INDEX(3, 7);
return tex_atlas_lookup(TEXAT_REDSTONE_TORCH);
}
static uint8_t getTextureIndex3(struct block_info* this, enum side side) {
return TEXTURE_INDEX(3, 6);
return tex_atlas_lookup(TEXAT_REDSTONE_TORCH_LIT);
}
struct block block_torch = {

View file

@ -69,7 +69,7 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
return TEXTURE_INDEX(8, 3);
return tex_atlas_lookup(TEXAT_TRAPDOOR);
}
struct block block_trapdoor = {

View file

@ -35,16 +35,24 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
}
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
if(this->block->metadata >= 9)
return TEXTURE_INDEX(1, 13 + 9 - this->block->metadata);
if(this->block->metadata == 8)
return TEXTURE_INDEX(3, 13);
if(this->block->metadata >= 1)
return TEXTURE_INDEX(2, 13 + 1 - this->block->metadata);
return TEXTURE_INDEX(0, 4);
switch(this->block->metadata) {
case 0: return tex_atlas_lookup(TEXAT_WOOL_0);
case 1: return tex_atlas_lookup(TEXAT_WOOL_1);
case 2: return tex_atlas_lookup(TEXAT_WOOL_2);
case 3: return tex_atlas_lookup(TEXAT_WOOL_3);
case 4: return tex_atlas_lookup(TEXAT_WOOL_4);
case 5: return tex_atlas_lookup(TEXAT_WOOL_5);
case 6: return tex_atlas_lookup(TEXAT_WOOL_6);
case 7: return tex_atlas_lookup(TEXAT_WOOL_7);
case 8: return tex_atlas_lookup(TEXAT_WOOL_8);
case 9: return tex_atlas_lookup(TEXAT_WOOL_9);
case 10: return tex_atlas_lookup(TEXAT_WOOL_10);
case 11: return tex_atlas_lookup(TEXAT_WOOL_11);
case 12: return tex_atlas_lookup(TEXAT_WOOL_12);
case 13: return tex_atlas_lookup(TEXAT_WOOL_13);
case 14: return tex_atlas_lookup(TEXAT_WOOL_14);
case 15: return tex_atlas_lookup(TEXAT_WOOL_15);
}
}
struct block block_wool = {

View file

@ -37,12 +37,12 @@ getSideMask(struct block_info* this, enum side side, struct block_info* it) {
static uint8_t getTextureIndex(struct block_info* this, enum side side) {
switch(side) {
case SIDE_FRONT:
case SIDE_LEFT: return TEXTURE_INDEX(12, 3);
case SIDE_LEFT: return tex_atlas_lookup(TEXAT_WORKBENCH_SIDE_2);
case SIDE_RIGHT:
case SIDE_BACK: return TEXTURE_INDEX(11, 3);
case SIDE_TOP: return TEXTURE_INDEX(11, 2);
case SIDE_BACK: return tex_atlas_lookup(TEXAT_WORKBENCH_SIDE_1);
case SIDE_TOP: return tex_atlas_lookup(TEXAT_WORKBENCH_TOP);
default:
case SIDE_BOTTOM: return TEXTURE_INDEX(4, 0);
case SIDE_BOTTOM: return tex_atlas_lookup(TEXAT_PLANKS);
}
}

View file

@ -23,13 +23,10 @@
#include <stdbool.h>
#include <stdint.h>
#include "../graphics/texture_atlas.h"
#include "../item/items.h"
#include "../platform/displaylist.h"
#define TEXTURE_INDEX(x, y) (((y)*14) + (x))
#define TEXTURE_X(idx) ((idx) % 14)
#define TEXTURE_Y(idx) ((idx) / 14)
enum block_material {
MATERIAL_WOOD,
MATERIAL_STONE,

View file

@ -21,6 +21,8 @@
#include "../platform/gfx.h"
#include "gui_util.h"
#include "render_block.h"
#include "texture_atlas.h"
int gutil_control_icon(int x, enum gutil_control_icon icon, char* str) {
gfx_bind_texture(TEXTURE_GUI);
@ -69,9 +71,14 @@ void gutil_bg() {
int cx = (gfx_width() + scale - 1) / scale;
int cy = (gfx_height() + scale - 1) / scale;
uint8_t tex = tex_atlas_lookup(TEXAT_DIRT);
uint8_t s = TEX_OFFSET(TEXTURE_X(tex));
uint8_t t = TEX_OFFSET(TEXTURE_Y(tex));
for(int y = 0; y < cy; y++) {
for(int x = 0; x < cx; x++) {
gutil_texquad_col(x * scale, y * scale, 39, 3, 16, 16, scale, scale,
gutil_texquad_col(x * scale, y * scale, s, t, 16, 16, scale, scale,
0x40, 0x40, 0x40, 0xFF);
}
}

View file

@ -0,0 +1,323 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include "../platform/texture.h"
#include "texture_atlas.h"
static uint8_t global_atlas[TEXAT_MAX];
static int clamp_n(int x, int n) {
if(x < 0)
return 0;
if(x > n - 1)
return n - 1;
return x;
}
void tex_atlas_reg(dict_atlas_src_t atlas, enum tex_atlas_entry name, uint8_t x,
uint8_t y) {
dict_atlas_src_push_back(atlas,
(struct texture_entry) {
.name = name,
.x = x,
.y = y,
.bg.enable = false,
.colorize.enable = false,
});
}
void tex_atlas_reg_col(dict_atlas_src_t atlas, enum tex_atlas_entry name,
uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b) {
dict_atlas_src_push_back(atlas,
(struct texture_entry) {
.name = name,
.x = x,
.y = y,
.bg.enable = false,
.colorize.enable = true,
.colorize.r = r,
.colorize.g = g,
.colorize.b = b,
});
}
void tex_atlas_reg_grass(dict_atlas_src_t atlas, enum tex_atlas_entry name,
uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b,
uint8_t bg_x, uint8_t bg_y) {
dict_atlas_src_push_back(atlas,
(struct texture_entry) {
.name = name,
.x = x,
.y = y,
.bg.enable = true,
.bg.x = bg_x,
.bg.y = bg_y,
.colorize.enable = true,
.colorize.r = r,
.colorize.g = g,
.colorize.b = b,
});
}
void* tex_atlas_compute(dict_atlas_src_t atlas, uint8_t* atlas_dst,
uint8_t* image, size_t width, size_t height) {
assert(image && width >= 256 && width == height);
int tile_size = width / 16;
int border_scale = width / 256;
uint8_t* output = malloc(width * height * 4);
if(!output)
return NULL;
memset(output, 255, width * height * 4);
dict_atlas_src_it_t it;
dict_atlas_src_it(it, atlas);
int current = 0;
while(!dict_atlas_src_end_p(it)) {
struct texture_entry* e = dict_atlas_src_ref(it);
size_t current_x = (current % 14) * (tile_size + 2 * border_scale)
+ 3 * border_scale;
size_t current_y = (current / 14) * (tile_size + 2 * border_scale)
+ 3 * border_scale;
for(int y = -border_scale; y < tile_size + border_scale; y++) {
for(int x = -border_scale; x < tile_size + border_scale; x++) {
uint8_t* src_col = image
+ ((clamp_n(x, tile_size) + e->x * tile_size)
+ (clamp_n(y, tile_size) + e->y * tile_size) * width)
* 4;
uint8_t* dst_col
= output + ((current_x + x) + (current_y + y) * width) * 4;
if(e->colorize.enable) {
dst_col[0] = src_col[0] * e->colorize.r / 255;
dst_col[1] = src_col[1] * e->colorize.g / 255;
dst_col[2] = src_col[2] * e->colorize.b / 255;
dst_col[3] = src_col[3];
} else {
for(size_t k = 0; k < 4; k++)
dst_col[k] = src_col[k];
}
if(e->bg.enable && dst_col[3] < 128) {
uint8_t* src_col2 = image
+ ((clamp_n(x, tile_size) + e->bg.x * tile_size)
+ (clamp_n(y, tile_size) + e->bg.y * tile_size)
* width)
* 4;
for(size_t k = 0; k < 4; k++)
dst_col[k] = src_col2[k];
}
}
}
atlas_dst[e->name] = TEXTURE_INDEX(current % 14, current / 14);
current++;
dict_atlas_src_next(it);
}
return output;
}
uint8_t tex_atlas_lookup(enum tex_atlas_entry name) {
return global_atlas[name];
}
void* tex_atlas_block(const char* filename, size_t* width, size_t* height) {
dict_atlas_src_t atlas;
dict_atlas_src_init(atlas);
tex_atlas_reg(atlas, TEXAT_STONE, 1, 0);
tex_atlas_reg(atlas, TEXAT_DIRT, 2, 0);
tex_atlas_reg(atlas, TEXAT_PLANKS, 4, 0);
tex_atlas_reg(atlas, TEXAT_SLAB_STONE_SIDE, 5, 0);
tex_atlas_reg(atlas, TEXAT_SLAB_STONE_TOP, 6, 0);
tex_atlas_reg(atlas, TEXAT_BRICKS, 7, 0);
tex_atlas_reg(atlas, TEXAT_TNT_SIDE, 8, 0);
tex_atlas_reg(atlas, TEXAT_TNT_TOP, 9, 0);
tex_atlas_reg(atlas, TEXAT_TNT_BOTTOM, 10, 0);
tex_atlas_reg(atlas, TEXAT_COBWEB, 11, 0);
tex_atlas_reg(atlas, TEXAT_ROSE, 12, 0);
tex_atlas_reg(atlas, TEXAT_DANDELION, 13, 0);
tex_atlas_reg(atlas, TEXAT_SAPLING_OAK, 15, 0);
tex_atlas_reg(atlas, TEXAT_COBBLESTONE, 0, 1);
tex_atlas_reg(atlas, TEXAT_BEDROCK, 1, 1);
tex_atlas_reg(atlas, TEXAT_SAND, 2, 1);
tex_atlas_reg(atlas, TEXAT_GRAVEL, 3, 1);
tex_atlas_reg(atlas, TEXAT_LOG_OAK_SIDE, 4, 1);
tex_atlas_reg(atlas, TEXAT_LOG_OAK_TOP, 5, 1);
tex_atlas_reg(atlas, TEXAT_CAST_BLOCK_IRON, 6, 1);
tex_atlas_reg(atlas, TEXAT_CAST_BLOCK_GOLD, 7, 1);
tex_atlas_reg(atlas, TEXAT_CAST_BLOCK_DIAMOND, 8, 1);
tex_atlas_reg(atlas, TEXAT_CHEST_TOP, 9, 1);
tex_atlas_reg(atlas, TEXAT_CHEST_SIDE, 10, 1);
tex_atlas_reg(atlas, TEXAT_CHEST_FRONT_SINGLE, 11, 1);
tex_atlas_reg(atlas, TEXAT_MUSHROOM_RED, 12, 1);
tex_atlas_reg(atlas, TEXAT_MUSHROOM_BROWN, 13, 1);
tex_atlas_reg(atlas, TEXAT_ORE_GOLD, 0, 2);
tex_atlas_reg(atlas, TEXAT_ORE_IRON, 1, 2);
tex_atlas_reg(atlas, TEXAT_ORE_COAL, 2, 2);
tex_atlas_reg(atlas, TEXAT_BOOKSHELF, 3, 2);
tex_atlas_reg(atlas, TEXAT_COBBLESTONE_MOSSY, 4, 2);
tex_atlas_reg(atlas, TEXAT_OBSIDIAN, 5, 2);
tex_atlas_reg(atlas, TEXAT_CHEST_FRONT_1, 9, 2);
tex_atlas_reg(atlas, TEXAT_CHEST_FRONT_2, 10, 2);
tex_atlas_reg(atlas, TEXAT_WORKBENCH_TOP, 11, 2);
tex_atlas_reg(atlas, TEXAT_FURNACE_FRONT, 12, 2);
tex_atlas_reg(atlas, TEXAT_FURNACE_SIDE, 13, 2);
tex_atlas_reg(atlas, TEXAT_DISPENSER_FRONT, 14, 2);
tex_atlas_reg(atlas, TEXAT_SPONGE, 0, 3);
tex_atlas_reg(atlas, TEXAT_GLASS, 1, 3);
tex_atlas_reg(atlas, TEXAT_ORE_DIAMOND, 2, 3);
tex_atlas_reg(atlas, TEXAT_ORE_REDSTONE, 3, 3);
tex_atlas_reg_col(atlas, TEXAT_LEAVES_BIRCH, 4, 3, 128, 167, 85);
tex_atlas_reg(atlas, TEXAT_DEADBUSH, 7, 3);
tex_atlas_reg(atlas, TEXAT_CHEST_BACK_1, 9, 3);
tex_atlas_reg(atlas, TEXAT_CHEST_BACK_2, 10, 3);
tex_atlas_reg(atlas, TEXAT_WORKBENCH_SIDE_1, 11, 3);
tex_atlas_reg(atlas, TEXAT_WORKBENCH_SIDE_2, 12, 3);
tex_atlas_reg(atlas, TEXAT_FURNACE_FRONT_LIT, 13, 3);
tex_atlas_reg(atlas, TEXAT_FURNACE_TOP, 14, 3);
tex_atlas_reg(atlas, TEXAT_SAPLING_SPRUCE, 15, 3);
tex_atlas_reg(atlas, TEXAT_SPAWNER, 1, 4);
tex_atlas_reg(atlas, TEXAT_SNOW, 2, 4);
tex_atlas_reg(atlas, TEXAT_GRASS_SIDE_SNOW, 4, 4);
tex_atlas_reg(atlas, TEXAT_CACTUS_TOP, 5, 4);
tex_atlas_reg(atlas, TEXAT_CACTUS_SIDE, 6, 4);
tex_atlas_reg(atlas, TEXAT_CACTUS_BOTTOM, 7, 4);
tex_atlas_reg(atlas, TEXAT_CLAY, 8, 4);
tex_atlas_reg(atlas, TEXAT_REED, 9, 4);
tex_atlas_reg(atlas, TEXAT_JUKBEBOX_SIDE, 10, 4);
tex_atlas_reg(atlas, TEXAT_JUKBEBOX_TOP, 11, 4);
tex_atlas_reg(atlas, TEXAT_SAPLING_BIRCH, 15, 4);
tex_atlas_reg(atlas, TEXAT_TORCH, 0, 5);
tex_atlas_reg(atlas, TEXAT_DOOR_WOOD_TOP, 1, 5);
tex_atlas_reg(atlas, TEXAT_DOOR_IRON_TOP, 2, 5);
tex_atlas_reg(atlas, TEXAT_LADDER, 3, 5);
tex_atlas_reg(atlas, TEXAT_TRAPDOOR, 4, 5);
tex_atlas_reg(atlas, TEXAT_FARMLAND_WET, 6, 5);
tex_atlas_reg(atlas, TEXAT_FARMLAND_DRY, 7, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_0, 8, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_1, 9, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_2, 10, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_3, 11, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_4, 12, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_5, 13, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_6, 14, 5);
tex_atlas_reg(atlas, TEXAT_CROPS_7, 15, 5);
// tex_atlas_reg(atlas, "lever", 0, 6);
tex_atlas_reg(atlas, TEXAT_DOOR_WOOD_BOTTOM, 1, 6);
tex_atlas_reg(atlas, TEXAT_DOOR_IRON_BOTTOM, 2, 6);
tex_atlas_reg(atlas, TEXAT_REDSTONE_TORCH_LIT, 3, 6);
tex_atlas_reg(atlas, TEXAT_PUMPKIN_TOP, 6, 6);
tex_atlas_reg(atlas, TEXAT_NETHERRACK, 7, 6);
tex_atlas_reg(atlas, TEXAT_SOULSAND, 8, 6);
tex_atlas_reg(atlas, TEXAT_GLOWSTONE, 9, 6);
/*tex_atlas_reg(atlas, "piston_front_sticky", 10, 6);
tex_atlas_reg(atlas, "piston_front", 11, 6);
tex_atlas_reg(atlas, "piston_side", 12, 6);
tex_atlas_reg(atlas, "piston_back", 13, 6);
tex_atlas_reg(atlas, "piston_inner", 14, 6);*/
tex_atlas_reg(atlas, TEXAT_RAIL_CURVED, 0, 7);
tex_atlas_reg(atlas, TEXAT_REDSTONE_TORCH, 3, 7);
tex_atlas_reg(atlas, TEXAT_LOG_SPRUCE_SIDE, 4, 7);
tex_atlas_reg(atlas, TEXAT_LOG_BIRCH_SIDE, 5, 7);
tex_atlas_reg(atlas, TEXAT_PUMPKIN_SIDE, 6, 7);
tex_atlas_reg(atlas, TEXAT_PUMPKIN_FRONT, 7, 7);
tex_atlas_reg(atlas, TEXAT_PUMPKIN_FRONT_LIT, 8, 7);
tex_atlas_reg(atlas, TEXAT_CAKE_TOP, 9, 7);
tex_atlas_reg(atlas, TEXAT_CAKE_SIDE, 10, 7);
tex_atlas_reg(atlas, TEXAT_CAKE_SIDE_CUT, 11, 7);
tex_atlas_reg(atlas, TEXAT_CAKE_BOTTOM, 12, 7);
tex_atlas_reg(atlas, TEXAT_RAIL, 0, 8);
// tex_atlas_reg(atlas, "repeater_off", 3, 8);
tex_atlas_reg_col(atlas, TEXAT_LEAVES_SPRUCE, 4, 8, 97, 153, 97);
tex_atlas_reg(atlas, TEXAT_BED_TOP_1, 6, 8);
tex_atlas_reg(atlas, TEXAT_BED_TOP_2, 7, 8);
tex_atlas_reg(atlas, TEXAT_CAST_BLOCK_LAPIS, 0, 9);
// tex_atlas_reg(atlas, "repeater_on", 3, 9);
tex_atlas_reg(atlas, TEXAT_BED_BACK, 5, 9);
tex_atlas_reg(atlas, TEXAT_BED_SIDE_1, 6, 9);
tex_atlas_reg(atlas, TEXAT_BED_SIDE_2, 7, 9);
tex_atlas_reg(atlas, TEXAT_BED_FRONT, 8, 9);
tex_atlas_reg(atlas, TEXAT_ORE_LAPIS, 0, 10);
tex_atlas_reg(atlas, TEXAT_RAIL_POWERED_OFF, 3, 10);
/*tex_atlas_reg_col(atlas, "redstone_intersect", 4, 10, 252, 49, 0);
tex_atlas_reg_col(atlas, "redstone_wire", 5, 10, 252, 49, 0);*/
tex_atlas_reg(atlas, TEXAT_SANDSTONE_TOP, 0, 11);
tex_atlas_reg(atlas, TEXAT_RAIL_POWERED_ON, 3, 11);
tex_atlas_reg(atlas, TEXAT_SANDSTONE_SIDE, 0, 12);
tex_atlas_reg(atlas, TEXAT_RAIL_DETECTOR, 3, 12);
tex_atlas_reg(atlas, TEXAT_SANDSTONE_BOTTOM, 0, 13);
tex_atlas_reg(atlas, TEXAT_WOOL_0, 0, 4);
tex_atlas_reg(atlas, TEXAT_WOOL_1, 2, 13);
tex_atlas_reg(atlas, TEXAT_WOOL_2, 2, 12);
tex_atlas_reg(atlas, TEXAT_WOOL_3, 2, 11);
tex_atlas_reg(atlas, TEXAT_WOOL_4, 2, 10);
tex_atlas_reg(atlas, TEXAT_WOOL_5, 2, 9);
tex_atlas_reg(atlas, TEXAT_WOOL_6, 2, 8);
tex_atlas_reg(atlas, TEXAT_WOOL_7, 2, 7);
tex_atlas_reg(atlas, TEXAT_WOOL_8, 1, 14);
tex_atlas_reg(atlas, TEXAT_WOOL_9, 1, 13);
tex_atlas_reg(atlas, TEXAT_WOOL_10, 1, 12);
tex_atlas_reg(atlas, TEXAT_WOOL_11, 1, 11);
tex_atlas_reg(atlas, TEXAT_WOOL_12, 1, 10);
tex_atlas_reg(atlas, TEXAT_WOOL_13, 1, 9);
tex_atlas_reg(atlas, TEXAT_WOOL_14, 1, 8);
tex_atlas_reg(atlas, TEXAT_WOOL_15, 1, 7);
tex_atlas_reg_col(atlas, TEXAT_GRASS_TOP, 0, 0, 110, 198, 63);
tex_atlas_reg_grass(atlas, TEXAT_GRASS_SIDE, 6, 2, 110, 198, 63, 3, 0);
tex_atlas_reg_col(atlas, TEXAT_TALLGRASS, 7, 2, 110, 198, 63);
tex_atlas_reg_col(atlas, TEXAT_LEAVES_OAK, 4, 3, 75, 182, 15);
tex_atlas_reg_col(atlas, TEXAT_FERN, 8, 3, 110, 198, 63);
memset(global_atlas, 0, sizeof(global_atlas));
uint8_t* image = tex_read(filename, width, height);
void* output
= tex_atlas_compute(atlas, global_atlas, image, *width, *height);
dict_atlas_src_clear(atlas);
free(image);
return output;
}

View file

@ -0,0 +1,197 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEXTURE_ATLAS_H
#define TEXTURE_ATLAS_H
#include <stdint.h>
#include <m-lib/m-array.h>
enum tex_atlas_entry {
TEXAT_STONE,
TEXAT_DIRT,
TEXAT_PLANKS,
TEXAT_SLAB_STONE_SIDE,
TEXAT_SLAB_STONE_TOP,
TEXAT_BRICKS,
TEXAT_TNT_SIDE,
TEXAT_TNT_TOP,
TEXAT_TNT_BOTTOM,
TEXAT_COBWEB,
TEXAT_ROSE,
TEXAT_DANDELION,
TEXAT_SAPLING_OAK,
TEXAT_COBBLESTONE,
TEXAT_BEDROCK,
TEXAT_SAND,
TEXAT_GRAVEL,
TEXAT_LOG_OAK_SIDE,
TEXAT_LOG_OAK_TOP,
TEXAT_CAST_BLOCK_IRON,
TEXAT_CAST_BLOCK_GOLD,
TEXAT_CAST_BLOCK_DIAMOND,
TEXAT_CHEST_TOP,
TEXAT_CHEST_SIDE,
TEXAT_CHEST_FRONT_SINGLE,
TEXAT_MUSHROOM_RED,
TEXAT_MUSHROOM_BROWN,
TEXAT_ORE_GOLD,
TEXAT_ORE_IRON,
TEXAT_ORE_COAL,
TEXAT_BOOKSHELF,
TEXAT_COBBLESTONE_MOSSY,
TEXAT_OBSIDIAN,
TEXAT_CHEST_FRONT_1,
TEXAT_CHEST_FRONT_2,
TEXAT_WORKBENCH_TOP,
TEXAT_FURNACE_FRONT,
TEXAT_FURNACE_SIDE,
TEXAT_DISPENSER_FRONT,
TEXAT_SPONGE,
TEXAT_GLASS,
TEXAT_ORE_DIAMOND,
TEXAT_ORE_REDSTONE,
TEXAT_LEAVES_BIRCH,
TEXAT_DEADBUSH,
TEXAT_CHEST_BACK_1,
TEXAT_CHEST_BACK_2,
TEXAT_WORKBENCH_SIDE_1,
TEXAT_WORKBENCH_SIDE_2,
TEXAT_FURNACE_FRONT_LIT,
TEXAT_FURNACE_TOP,
TEXAT_SAPLING_SPRUCE,
TEXAT_SPAWNER,
TEXAT_SNOW,
TEXAT_GRASS_SIDE_SNOW,
TEXAT_CACTUS_TOP,
TEXAT_CACTUS_SIDE,
TEXAT_CACTUS_BOTTOM,
TEXAT_CLAY,
TEXAT_REED,
TEXAT_JUKBEBOX_SIDE,
TEXAT_JUKBEBOX_TOP,
TEXAT_SAPLING_BIRCH,
TEXAT_TORCH,
TEXAT_DOOR_WOOD_TOP,
TEXAT_DOOR_IRON_TOP,
TEXAT_LADDER,
TEXAT_TRAPDOOR,
TEXAT_FARMLAND_WET,
TEXAT_FARMLAND_DRY,
TEXAT_CROPS_0,
TEXAT_CROPS_1,
TEXAT_CROPS_2,
TEXAT_CROPS_3,
TEXAT_CROPS_4,
TEXAT_CROPS_5,
TEXAT_CROPS_6,
TEXAT_CROPS_7,
TEXAT_DOOR_WOOD_BOTTOM,
TEXAT_DOOR_IRON_BOTTOM,
TEXAT_REDSTONE_TORCH_LIT,
TEXAT_PUMPKIN_TOP,
TEXAT_NETHERRACK,
TEXAT_SOULSAND,
TEXAT_GLOWSTONE,
TEXAT_RAIL_CURVED,
TEXAT_REDSTONE_TORCH,
TEXAT_LOG_SPRUCE_SIDE,
TEXAT_LOG_BIRCH_SIDE,
TEXAT_PUMPKIN_SIDE,
TEXAT_PUMPKIN_FRONT,
TEXAT_PUMPKIN_FRONT_LIT,
TEXAT_CAKE_TOP,
TEXAT_CAKE_SIDE,
TEXAT_CAKE_SIDE_CUT,
TEXAT_CAKE_BOTTOM,
TEXAT_RAIL,
TEXAT_LEAVES_SPRUCE,
TEXAT_BED_TOP_1,
TEXAT_BED_TOP_2,
TEXAT_CAST_BLOCK_LAPIS,
TEXAT_BED_BACK,
TEXAT_BED_SIDE_1,
TEXAT_BED_SIDE_2,
TEXAT_BED_FRONT,
TEXAT_ORE_LAPIS,
TEXAT_RAIL_POWERED_OFF,
TEXAT_SANDSTONE_TOP,
TEXAT_RAIL_POWERED_ON,
TEXAT_SANDSTONE_SIDE,
TEXAT_RAIL_DETECTOR,
TEXAT_SANDSTONE_BOTTOM,
TEXAT_WOOL_0,
TEXAT_WOOL_1,
TEXAT_WOOL_2,
TEXAT_WOOL_3,
TEXAT_WOOL_4,
TEXAT_WOOL_5,
TEXAT_WOOL_6,
TEXAT_WOOL_7,
TEXAT_WOOL_8,
TEXAT_WOOL_9,
TEXAT_WOOL_10,
TEXAT_WOOL_11,
TEXAT_WOOL_12,
TEXAT_WOOL_13,
TEXAT_WOOL_14,
TEXAT_WOOL_15,
TEXAT_GRASS_TOP,
TEXAT_GRASS_SIDE,
TEXAT_TALLGRASS,
TEXAT_LEAVES_OAK,
TEXAT_FERN,
TEXAT_MAX,
};
struct texture_entry {
enum tex_atlas_entry name;
uint8_t x : 4, y : 4;
struct {
bool enable;
uint8_t r, g, b;
} colorize;
struct {
bool enable;
uint8_t x : 4, y : 4;
} bg;
};
ARRAY_DEF(dict_atlas_src, struct texture_entry, M_POD_OPLIST)
#define TEXTURE_INDEX(x, y) (((y)*14) + (x))
#define TEXTURE_X(idx) ((idx) % 14)
#define TEXTURE_Y(idx) ((idx) / 14)
void tex_atlas_reg(dict_atlas_src_t atlas, enum tex_atlas_entry name, uint8_t x,
uint8_t y);
void tex_atlas_reg_col(dict_atlas_src_t atlas, enum tex_atlas_entry name,
uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b);
void tex_atlas_reg_grass(dict_atlas_src_t atlas, enum tex_atlas_entry name,
uint8_t x, uint8_t y, uint8_t r, uint8_t g, uint8_t b,
uint8_t bg_x, uint8_t bg_y);
void* tex_atlas_compute(dict_atlas_src_t atlas, uint8_t* atlas_dst,
uint8_t* image, size_t width, size_t height);
uint8_t tex_atlas_lookup(enum tex_atlas_entry name);
void* tex_atlas_block(const char* filename, size_t* width, size_t* height);
#endif

View file

@ -25,61 +25,45 @@
#include <string.h>
#include "../../game/game_state.h"
#include "../../graphics/texture_atlas.h"
#include "../../lodepng/lodepng.h"
#include "../../util.h"
#include "../gfx.h"
#include "../input.h"
#include "../texture.h"
static GLuint textures[8];
static GLuint load_tex(const char* filename, bool nearest) {
unsigned width, height;
unsigned char* img;
if(lodepng_decode32_file(&img, &width, &height, filename))
printf("error loading texture %s\n", filename);
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
nearest ? GL_NEAREST : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
nearest ? GL_NEAREST : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
free(img);
return tex;
}
static void gfx_load_textures() {
textures[0] = load_tex("terrain.png", true);
textures[1] = load_tex("default.png", true);
textures[2] = load_tex("anim.png", true);
textures[3] = load_tex("gui.png", true);
textures[4] = load_tex("gui_2.png", true);
textures[5] = load_tex("items.png", true);
glGenTextures(6, textures);
size_t w, h;
void* output = tex_atlas_block("assets/terrain.png", &w, &h);
if(output) {
tex_gfx_load(output, w, h, TEX_FMT_RGBA16, textures[0], false);
free(output);
}
tex_gfx_load_file("assets/default.png", TEX_FMT_I8, textures[1], false);
tex_gfx_load_file("assets/anim.png", TEX_FMT_RGBA32, textures[2], false);
tex_gfx_load_file("assets/gui.png", TEX_FMT_IA4, textures[3], false);
tex_gfx_load_file("assets/gui_2.png", TEX_FMT_RGBA16, textures[4], false);
tex_gfx_load_file("assets/items.png", TEX_FMT_RGBA16, textures[5], false);
}
static void testtest(GLuint shader) {
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE) {
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
static void shader_error(GLuint shader) {
GLint is_compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled);
// The maxLength includes the NULL character
char log[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, log);
if(!is_compiled) {
GLint length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
char log[length];
glGetShaderInfoLog(shader, length, &length, log);
printf("%s\n", log);
// Provide the infolog in whatever manor you deem best.
// Exit with failure.
glDeleteShader(shader); // Don't leak the shader.
glDeleteShader(shader);
}
}
@ -87,12 +71,12 @@ static GLuint create_shader(const char* vertex, const char* fragment) {
GLuint v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, (const GLchar* const*)&vertex, NULL);
glCompileShader(v);
testtest(v);
shader_error(v);
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, (const GLchar* const*)&fragment, NULL);
glCompileShader(f);
testtest(f);
shader_error(f);
GLuint program = glCreateProgram();
glAttachShader(program, v);
@ -208,9 +192,9 @@ void gfx_setup() {
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("Version: %s\n", glGetString(GL_VERSION));
void* vertex = file_read("vertex.shader");
void* vertex = file_read("assets/vertex.shader");
assert(vertex);
void* fragment = file_read("fragment.shader");
void* fragment = file_read("assets/fragment.shader");
assert(fragment);
shader_prog = create_shader(vertex, fragment);

View file

@ -0,0 +1,36 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#include <GL/glew.h>
void tex_gfx_load(void* img, size_t width, size_t height, enum tex_format type,
int slot, bool linear) {
assert(img && width > 0 && height > 0);
glBindTexture(GL_TEXTURE_2D, slot);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, img);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
linear ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
linear ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
}

61
source/platform/texture.c Normal file
View file

@ -0,0 +1,61 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdlib.h>
#include "../lodepng/lodepng.h"
#include "texture.h"
uint8_t* tex_read(const char* filename, size_t* width, size_t* height) {
assert(filename && width && height);
uint8_t* img;
unsigned w, h;
if(lodepng_decode32_file(&img, &w, &h, filename))
return NULL;
*width = w;
*height = h;
return img;
}
void tex_gfx_load_file(const char* filename, enum tex_format type, int slot,
bool linear) {
assert(filename);
size_t width, height;
void* img = tex_read(filename, &width, &height);
if(!img)
return;
tex_gfx_load(img, width, height, type, slot, linear);
free(img);
}
#ifdef PLATFORM_WII
#include "wii/texture.c"
#endif
#ifdef PLATFORM_PC
#include "pc/texture.c"
#endif

41
source/platform/texture.h Normal file
View file

@ -0,0 +1,41 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEXTURE_H
#define TEXTURE_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
enum tex_format {
TEX_FMT_RGBA16,
TEX_FMT_RGBA32,
TEX_FMT_I8,
TEX_FMT_IA4,
};
uint8_t* tex_read(const char* filename, size_t* width, size_t* height);
void tex_gfx_load(void* img, size_t width, size_t height, enum tex_format type,
int slot, bool linear);
void tex_gfx_load_file(const char* filename, enum tex_format type, int slot,
bool linear);
#endif

View file

@ -24,11 +24,10 @@
#include <ogc/tpl.h>
#include <string.h>
#include "../../graphics/texture_atlas.h"
#include "../../util.h"
#include "../gfx.h"
#include "textures.h"
#include "textures_tpl.h"
#include "../texture.h"
#define FIFO_SIZE (256 * 1024)
@ -82,47 +81,44 @@ static void copy_buffers(u32 cnt) {
}
}
#define distance_2d(x1, y1, x2, y2) \
(((x1) - (x2)) * ((x1) - (x2)) + ((y1) - (y2)) * ((y1) - (y2)))
static void texture_fog(uint8_t* img, size_t size) {
for(size_t y = 0; y < size; y++) {
for(size_t x = 0; x < size; x++) {
float d = (sqrt(distance_2d(size / 2.0F, size / 2.0F, x + 0.5F,
y + 0.5F))
- (size / 2.0F - 9.0F))
/ 8.0F;
uint8_t* pixel = img + (x + y * size) * 4;
pixel[0] = pixel[1] = pixel[2]
= roundf(glm_clamp(d * 255.0F, 0.0F, 255.0F));
pixel[3] = 255;
}
}
}
static void gfx_load_textures() {
GXTexObj terrain, font, anim, gui, gui2, items, fog;
TPLFile spriteTPL;
TPL_OpenTPLFromMemory(&spriteTPL, (void*)textures_tpl, textures_tpl_size);
TPL_GetTexture(&spriteTPL, texture_terrain, &terrain);
GX_InitTexObjFilterMode(&terrain, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&terrain, GX_ANISO_1);
GX_LoadTexObj(&terrain, GX_TEXMAP0);
size_t w, h;
void* output = tex_atlas_block("assets/terrain.png", &w, &h);
if(output) {
tex_gfx_load(output, w, h, TEX_FMT_RGBA16, GX_TEXMAP0, false);
free(output);
}
TPL_GetTexture(&spriteTPL, texture_font, &font);
GX_InitTexObjFilterMode(&font, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&font, GX_ANISO_1);
GX_LoadTexObj(&font, GX_TEXMAP1);
tex_gfx_load_file("assets/default.png", TEX_FMT_I8, GX_TEXMAP1, false);
tex_gfx_load_file("assets/anim.png", TEX_FMT_RGBA32, GX_TEXMAP2, false);
tex_gfx_load_file("assets/gui.png", TEX_FMT_IA4, GX_TEXMAP3, false);
tex_gfx_load_file("assets/gui_2.png", TEX_FMT_RGBA16, GX_TEXMAP4, false);
tex_gfx_load_file("assets/items.png", TEX_FMT_RGBA16, GX_TEXMAP5, false);
TPL_GetTexture(&spriteTPL, texture_anim, &anim);
GX_InitTexObjFilterMode(&anim, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&anim, GX_ANISO_1);
GX_LoadTexObj(&anim, GX_TEXMAP2);
TPL_GetTexture(&spriteTPL, texture_gui, &gui);
GX_InitTexObjFilterMode(&gui, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&gui, GX_ANISO_1);
GX_LoadTexObj(&gui, GX_TEXMAP3);
TPL_GetTexture(&spriteTPL, texture_gui2, &gui2);
GX_InitTexObjFilterMode(&gui2, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&gui2, GX_ANISO_1);
GX_LoadTexObj(&gui2, GX_TEXMAP4);
TPL_GetTexture(&spriteTPL, texture_items, &items);
GX_InitTexObjFilterMode(&items, GX_NEAR, GX_NEAR);
GX_InitTexObjMaxAniso(&items, GX_ANISO_1);
GX_LoadTexObj(&items, GX_TEXMAP5);
TPL_GetTexture(&spriteTPL, texture_fog, &fog);
GX_InitTexObjFilterMode(&fog, GX_LINEAR, GX_LINEAR);
GX_InitTexObjMaxAniso(&fog, GX_ANISO_1);
GX_InitTexObjWrapMode(&fog, GX_CLAMP, GX_CLAMP);
GX_LoadTexObj(&fog, GX_TEXMAP7);
TPL_CloseTPLFile(&spriteTPL);
size_t fog_size = 128;
uint8_t* fog = malloc(fog_size * fog_size * 4);
texture_fog(fog, fog_size);
tex_gfx_load(fog, fog_size, fog_size, TEX_FMT_I8, GX_TEXMAP6, true);
free(fog);
}
int gfx_width() {
@ -389,7 +385,7 @@ void gfx_fog(bool enable) {
if(enable) {
GX_SetTevOp(GX_TEVSTAGE1, GX_DECAL);
GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP7, GX_COLOR0A0);
GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP6, GX_COLOR0A0);
GX_SetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_C0, GX_CC_TEXA,
GX_CC_ZERO);
}

View file

@ -0,0 +1,187 @@
/*
Copyright (c) 2023 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <gccore.h>
#include <malloc.h>
#define rgba16(r, g, b, a) \
(((int)(a) << 12) | ((int)(r) << 8) | ((int)(g) << 4) | (int)(b))
#define rgb16(r, g, b) (0x8000 | ((int)(r) << 10) | ((int)(g) << 5) | (int)(b))
#define xy16(x, y) (((int)(x) << 8) | (int)(y))
#define ia8(i, a) (((int)(a) << 4) | (int)(i))
static void* tex_conv_rgb32(uint8_t* image, size_t width, size_t height) {
assert(image && (width % 4) == 0 && (height % 4) == 0);
uint16_t* output = memalign(32, width * height * sizeof(uint16_t) * 2);
if(!output)
return NULL;
size_t output_idx = 0;
for(size_t y = 0; y < height; y += 4) {
for(size_t x = 0; x < width; x += 4) {
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 4; bx++) {
uint8_t* col = image + (x + bx + (y + by) * width) * 4;
output[output_idx++] = xy16(col[3], col[0]);
}
}
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 4; bx++) {
uint8_t* col = image + (x + bx + (y + by) * width) * 4;
output[output_idx++] = xy16(col[1], col[2]);
}
}
}
}
DCFlushRange(output, width * height * sizeof(uint16_t) * 2);
return output;
}
static void* tex_conv_rgb16(uint8_t* image, size_t width, size_t height) {
assert(image && (width % 4) == 0 && (height % 4) == 0);
uint16_t* output = memalign(32, width * height * sizeof(uint16_t));
if(!output)
return NULL;
size_t output_idx = 0;
for(size_t y = 0; y < height; y += 4) {
for(size_t x = 0; x < width; x += 4) {
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 4; bx++) {
uint8_t* col = image + (x + bx + (y + by) * width) * 4;
int alpha = col[3] >> 5;
if(alpha < 7) {
output[output_idx++] = rgba16(col[0] >> 4, col[1] >> 4,
col[2] >> 4, alpha);
} else {
output[output_idx++]
= rgb16(col[0] >> 3, col[1] >> 3, col[2] >> 3);
}
}
}
}
}
DCFlushRange(output, width * height * sizeof(uint16_t));
return output;
}
static void* tex_conv_i8(uint8_t* image, size_t width, size_t height) {
assert(image && (width % 8) == 0 && (height % 4) == 0);
uint8_t* output = memalign(32, width * height * sizeof(uint8_t));
if(!output)
return NULL;
size_t output_idx = 0;
for(size_t y = 0; y < height; y += 4) {
for(size_t x = 0; x < width; x += 8) {
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 8; bx++) {
uint8_t* col = image + (x + bx + (y + by) * width) * 4;
output[output_idx++]
= ((int)col[0] + (int)col[1] + (int)col[2]) / 3;
}
}
}
}
DCFlushRange(output, width * height * sizeof(uint8_t));
return output;
}
static void* tex_conv_ia4(uint8_t* image, size_t width, size_t height) {
assert(image && (width % 8) == 0 && (height % 4) == 0);
uint8_t* output = memalign(32, width * height * sizeof(uint8_t));
if(!output)
return NULL;
size_t output_idx = 0;
for(size_t y = 0; y < height; y += 4) {
for(size_t x = 0; x < width; x += 8) {
for(size_t by = 0; by < 4; by++) {
for(size_t bx = 0; bx < 8; bx++) {
uint8_t* col = image + (x + bx + (y + by) * width) * 4;
output[output_idx++] = ia8(
(((int)col[0] + (int)col[1] + (int)col[2]) / 3) >> 4,
col[3] >> 4);
}
}
}
}
DCFlushRange(output, width * height * sizeof(uint8_t));
return output;
}
void tex_gfx_load(void* img, size_t width, size_t height, enum tex_format type,
int slot, bool linear) {
assert(img && width > 0 && height > 0);
void* output = NULL;
uint8_t fmt;
switch(type) {
case TEX_FMT_RGBA32:
output = tex_conv_rgb32(img, width, height);
fmt = GX_TF_RGBA8;
break;
case TEX_FMT_RGBA16:
output = tex_conv_rgb16(img, width, height);
fmt = GX_TF_RGB5A3;
break;
case TEX_FMT_I8:
output = tex_conv_i8(img, width, height);
fmt = GX_TF_I8;
break;
case TEX_FMT_IA4:
output = tex_conv_ia4(img, width, height);
fmt = GX_TF_IA4;
break;
default: return;
}
if(output) {
GXTexObj obj;
GX_InitTexObj(&obj, output, width, height, fmt, GX_CLAMP, GX_CLAMP,
GX_FALSE);
GX_InitTexObjMaxAniso(&obj, GX_ANISO_1);
GX_InitTexObjFilterMode(&obj, linear ? GX_LINEAR : GX_NEAR,
linear ? GX_LINEAR : GX_NEAR);
GX_LoadTexObj(&obj, slot);
// TODO: data needed by gpu, must not free
// free(output);
}
}