Huge skylight optimizations. Also fixed the submodules.

This commit is contained in:
milkwx3
2026-07-04 01:48:50 +03:00
parent 85ddc90883
commit 7ab2d5a083
7 changed files with 81 additions and 52 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[submodule "src/libraries/enet"]
path = src/libraries/enet
url = https://github.com/zpl-c/enet
url = https://github.com/lsalzman/enet
[submodule "src/libraries/Lua"]
path = src/libraries/Lua
url = https://github.com/walterschell/Lua
+54 -31
View File
@@ -23,7 +23,7 @@ static const siv::PerlinNoise perlin;
static int world_type = 0;
const BlockDef BLOCKS[] = {
std::vector<BlockDef> BLOCKS = {
BlockDef{ "air", R_Translucent, B_Stone, 0, 0, 0},
BlockDef{ "stone", R_Normal, B_Stone, 7, 0, 3},
BlockDef{ "grass", R_TriSide, B_Grass, 1, 0, 0, 1, 2},
@@ -40,8 +40,8 @@ const BlockDef BLOCKS[] = {
BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13},
BlockDef{ "spruce_log", R_TriSide, B_Wood, 5, 0, 21, 20, 21},
BlockDef{ "workbench", R_TranslucentAllSides, B_Stone, 3, 0, 23, 22, 23},
BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 22},
BlockDef{ "yellow_block", R_Normal, B_Stone, 5, 0, 23},
BlockDef{ "undefined", R_Normal, B_Stone, 5, 0, 22},
BlockDef{ "undefined", R_Normal, B_Stone, 5, 0, 23},
BlockDef{ "red_block", R_Normal, B_Stone, 5, 0, 24},
BlockDef{ "green_block", R_Normal, B_Stone, 5, 0, 25},
BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 26},
@@ -53,9 +53,14 @@ const BlockDef BLOCKS[] = {
BlockDef{ "coal_ore", R_Normal, B_Stone, 7, 0, 8},
BlockDef{ "unobtainium", R_Normal, B_Stone, 7, 999, 3}, // Bedrock?
};
BlockDef &GetBlockDefinition(int id) {
return BLOCKS[id];
}
void LoadBlocks() {
}
int GetNumericIDFromString(std::string s) {
int count = sizeof(BLOCKS) / sizeof(BLOCKS[0]);
for (int i = 0; i < count; ++i) {
for (int i = 0; i < BLOCKS.size(); ++i) {
if (BLOCKS[i].name == s) return i;
}
return -1;
@@ -118,7 +123,7 @@ int GetHighestBlock(World &world, int x, int z) {
return world.chunks[GetIndexWorld(cx, cz)].highestBlock[GetIndexChunk2D(locX, locZ)];
}
int GetSkyLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return 0;
if(CheckOOBWorld(x, y, z)) return 15;
int locX = x % CHUNK_SIZE;
int locZ = z % CHUNK_SIZE;
int cx = x / CHUNK_SIZE;
@@ -164,18 +169,14 @@ Color GetLight(World &world, int x, int y, int z) {
int cx = x / CHUNK_SIZE;
int cz = z / CHUNK_SIZE;
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
int skyLight = ((light >> 12) & 0xF) * 16;
Color sky = {skyLight, skyLight, skyLight, 255};
Color r = {((light >> 8) & 0xF) * 16 + skyLight, 0, 0, 255};
Color g = {0, ((light >> 4) & 0xF) * 16 + skyLight, 0, 255};
Color b = {0, 0, ((light >> 0) & 0xF) * 16 + skyLight, 255};
Color f = ColorTint(sky, r);
f = ColorTint(f, g);
f = ColorTint(f, b);
int skyLight = powf(((light >> 12) & 0xF) / 15.0f, 1) * 255;
Color r = {((light >> 8) & 0xF) * 16, 0, 0, 255};
Color g = {0, ((light >> 4) & 0xF) * 16, 0, 255};
Color b = {0, 0, ((light >> 0) & 0xF) * 16, 255};
return {
fmin((int)sky.r + (int)r.r, 255),
fmin((int)sky.g + (int)g.g, 255),
fmin((int)sky.b + (int)b.b, 255),
fmin((int)skyLight + (int)r.r, 255),
fmin((int)skyLight + (int)g.g, 255),
fmin((int)skyLight + (int)b.b, 255),
255
};
}
@@ -310,12 +311,12 @@ void SetLight(World &world, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t
}
void InitWorldgen(int worldType) {
const siv::PerlinNoise::seed_type seed = 123456u;
const siv::PerlinNoise::seed_type seed = 0u;
const siv::PerlinNoise perlin{ seed };
constexpr size_t MAX = 128; // allowed range: 0..MAX-1
for (int i = 0; i < sizeof(BLOCKS) / sizeof(BlockDef); i++)
for (int i = 0; i < BLOCKS.size(); i++)
{
BlockDef def = BLOCKS[i];
BlockDef def = GetBlockDefinition(i);
if(def.render == R_Translucent || def.render == R_TranslucentAllSides || def.render == R_TranslucentTriSide) {
marked.set(i);
}
@@ -619,28 +620,52 @@ void RebuildLighting(World &world, int startX, int startZ) {
memset(&chunk.light, 0, sizeof(chunk.light));
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
int y = chunk.highestBlock[GetIndexChunk2D(x, z)];
if (y < 0) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y + 1, z + chunk.z * CHUNK_SIZE };
if (CheckOOBWorld(pos.x, pos.y, pos.z)) continue;
int highest = chunk.highestBlock[GetIndexChunk2D(x, z)];
const int neighbors[4] = {
chunk.highestBlock[GetIndexChunk2D(x-1, z)],
chunk.highestBlock[GetIndexChunk2D(x+1, z)],
chunk.highestBlock[GetIndexChunk2D(x, z-1)],
chunk.highestBlock[GetIndexChunk2D(x, z+1)]
};
int highestNeighbor = fmax(neighbors[0], fmax(neighbors[1], fmax(neighbors[2], neighbors[3])));
Vector3I pos = { x + chunk.x * CHUNK_SIZE, highest + 1, z + chunk.z * CHUNK_SIZE };
for (int _y = WORLD_HEIGHT; _y >= y; _y--)
for (int y = highest + 1; y <= WORLD_HEIGHT; ++y)
{
SetLight(world, pos.x, _y, pos.z, 15, 0, 0, 0);
SetLightChunk(&chunk, x, y, z, 15, 0, 0, 0);
}
LightNode node{pos, 15};
nodes.push(node);
if (highest == highestNeighbor) continue;
for (int y = highest+1; y < highestNeighbor+1; y++)
{
if (
GetSkyLight(world, pos.x-1, y, pos.z) < 15 && !TestOpaqueMaskWorld(world, pos.x-1, y, pos.z)
) nodes.push({(Vector3I){pos.x-1, y, pos.z}, 15});
if (
GetSkyLight(world, pos.x+1, y, pos.z) < 15 && !TestOpaqueMaskWorld(world, pos.x+1, y, pos.z)
) nodes.push({(Vector3I){pos.x+1, y, pos.z}, 15});
if (
GetSkyLight(world, pos.x, y, pos.z-1) < 15 && !TestOpaqueMaskWorld(world, pos.x, y, pos.z-1)
) nodes.push({(Vector3I){pos.x, y, pos.z-1}, 15});
if (
GetSkyLight(world, pos.x, y, pos.z+1) < 15 && !TestOpaqueMaskWorld(world, pos.x, y, pos.z+1)
) nodes.push({(Vector3I){pos.x, y, pos.z+1}, 15});
}
}
}
}
}
std::cout << nodes.size() << std::endl;
while (!nodes.empty()) {
LightNode node = nodes.front();
nodes.pop();
for (int i = 0; i < 6; i++) {
int newValue = node.value - 1;
if (newValue <= 0) continue;
Vector3I newPos = {
node.position.x + dirs[i].x,
node.position.y + dirs[i].y,
@@ -649,8 +674,6 @@ void RebuildLighting(World &world, int startX, int startZ) {
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
int newValue = node.value - 1;
if (newValue <= 0) continue;
if (GetSkyLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
+2 -1
View File
@@ -303,7 +303,8 @@ typedef struct World World;
struct World {
Chunk chunks[MAX_WORLD_AREA];
};
extern const BlockDef BLOCKS[];
BlockDef&GetBlockDefinition(int id);
void LoadBlocks();
int GetBlock(World&world,int x,int y,int z);
int GetHighestBlock(World&world,int x,int z);
int GetSkyLight(World&world,int x,int y,int z);
+1 -1
View File
@@ -363,7 +363,7 @@ void DrawEntities(float dt) {
DrawCube(pos_lerped, 1, 1, 1, RED);
}
if(ent.type == 4) {
DrawCubeBlock(terrain, pos_lerped, 1,1,1, BLOCKS[ent.data[1]]);
DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1]));
}
}
}
+7 -7
View File
@@ -40,7 +40,7 @@ void DrawItem(InventoryItem item, int x, int y) {
if(item.item->type == IType_Block) {
atlas = terrain;
atl_size = ATLAS_SIZE_W;
tex = BLOCKS[item.damage].textureTop;
tex = GetBlockDefinition(item.damage).textureTop;
}
DrawTexturePro(atlas,
{
@@ -198,9 +198,9 @@ static bool GetTaggedItem(std::string tag, InventoryItem* item) {
bool isBlock;
bool found;
for(int blk = 0; blk < MAX_BLOCK_ID; blk++) {
if(IDTagMatch(tag, BLOCKS[blk].name)) {
if(IDTagMatch(tag, GetBlockDefinition(blk).name)) {
isBlock = true;
id = GetNumericIDFromString(BLOCKS[blk].name);
id = GetNumericIDFromString(GetBlockDefinition(blk).name);
found = true;
break;
};
@@ -307,7 +307,7 @@ void DrawHotbar() {
if(item.item != nullptr) {
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items.push_back(i);
@@ -366,7 +366,7 @@ void DrawHotbar() {
if(item.item != nullptr) {
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items[i] = ingredient.quantity;
@@ -432,7 +432,7 @@ void DrawHotbar() {
DrawItem(*movingItem, GetMouseX(), GetMouseY());
std::string name = "item."+movingItem->item->id;
if(movingItem->item->type == IType_Block) {
name = "item."+BLOCKS[movingItem->damage].name;
name = "item."+GetBlockDefinition(movingItem->damage).name;
}
DrawTextB(LocaleGet(name).c_str(), GetMouseX()-16, GetMouseY()+56, 16, WHITE);
}
@@ -461,7 +461,7 @@ void DrawSelectedItem() {
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
if(item.item != nullptr) {
if(item.item->type == IType_Block) {
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, BLOCKS[item.damage]);
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, GetBlockDefinition(item.damage));
}
else {
UVCorners left = GetUVTex(item.item->texture);
+4 -5
View File
@@ -23,21 +23,20 @@ MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk
std::vector<unsigned short> indices;
int face = 0;
for (int x = 0; x < CHUNK_SIZE; ++x)
for (int y = 0; y < WORLD_HEIGHT; ++y)
for (int z = 0; z < CHUNK_SIZE; ++z)
for (int index = 0; index < CHUNK_DATA_SIZE; index++)
{
int index = GetIndexChunk(x,y,z);
uint8_t crdata = chunkRenderData.sides[index];
if (crdata == 0) continue;
int x, y, z;
GetXYZFromIndex(index, &x, &y, &z);
int wx = (chunkWorldX * CHUNK_SIZE + x);
int wy = (y);
int wz = (chunkWorldY * CHUNK_SIZE + z);
int this_block = fetch_block(chunk, x,y,z);
BlockDef definition = BLOCKS[this_block];
BlockDef definition = GetBlockDefinition(this_block);
UVCorners UVside = GetUVTex(definition.textureSide);
UVCorners UVtop = GetUVTex(definition.textureTop);
+12 -6
View File
@@ -409,11 +409,11 @@ void SetBlockNetwork(World &world, int bx, int by, int bz, int t) {
tickedBlocks.push({bx, by, bz-1});
tickedBlocks.push({bx, by, bz+1});
if(t != 0) {
sound = BLOCKS[t].type;
sound = GetBlockDefinition(t).type;
}
else {
int id = GetBlock(world, bx, by, bz);
BlockDef block = BLOCKS[id];
BlockDef block = GetBlockDefinition(id);
if(id != 0) {
sound = block.type;
for (int x = 0; x < 4; x++)
@@ -730,7 +730,7 @@ static void GameUpdate(Camera camera, float &time) {
tier = selected_item->tier;
}
}
BlockDef block = BLOCKS[GetBlock(world, bx, by, bz)];
BlockDef block = GetBlockDefinition(GetBlock(world, bx, by, bz));
float hardnessMultiplier = block.hardness / 4.0f;
if(player_break_parts_time >= 0.05f) {
Vector3 v = {0, 1, 0};
@@ -1053,7 +1053,7 @@ static void GameUpdate(Camera camera, float &time) {
oxygen += dt * 20.0f;
oxygen = Clamp(oxygen, 0, MAX_HP);
}
if(!hide_ui && !taking_panorama) {
if(!hide_ui && !taking_panorama) { // DEBUG MENU!!!!
char text[128];
sprintf(text, "%s %s", GAME_NAME, GAME_VERSION);
DrawTextB(text, 20, 20, DEFAULT_FONT_SIZE, WHITE);
@@ -1068,8 +1068,14 @@ static void GameUpdate(Camera camera, float &time) {
float virtualmem = m.virtualSize / 1024.0f / 1024.0f;
sprintf(text, "Mem %.2fMiB/%.2fMiB", residentmem, virtualmem);
DrawTextB(text, 20, 80, DEFAULT_FONT_SIZE, WHITE);
sprintf(text, "Drawing %d verts", debug_verts_opaque+debug_verts_transparent);
DrawTextB(text, 120, 40, DEFAULT_FONT_SIZE, WHITE);
Vector3I ppos = {floorf(player_position.x), floorf(player_position.y), floorf(player_position.z)};
sprintf(text, "skylight %d | blocklight: r %d g %d b %d",
GetSkyLight(world, ppos.x, ppos.y, ppos.z),
GetRLight(world, ppos.x, ppos.y, ppos.z),
GetGLight(world, ppos.x, ppos.y, ppos.z),
GetBLight(world, ppos.x, ppos.y, ppos.z)
);
DrawTextB(text, 20, 100, DEFAULT_FONT_SIZE, WHITE);
DrawRectangle(GetScreenWidth()/2-3, GetScreenHeight()/2-3, 6, 6, BLACK);
DrawRectangle(GetScreenWidth()/2-2, GetScreenHeight()/2-2, 4, 4, WHITE);