Colored block lighting

This commit is contained in:
milkwx3
2026-06-24 20:25:11 +03:00
parent d02d751275
commit 85ddc90883
6 changed files with 217 additions and 25 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
# echo "deb [signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://archive.ubuntu.com/ubuntu noble main" | sudo tee /tmp/only.list
# sudo apt-get update -o Dir::Etc::sourcelist=/tmp/only.list -o Dir::Etc::sourceparts="-" -qq
sudo apt update
sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-i686-x86-64 gcc-mingw-i686-x86-64 libxinerama-dev libxcursor-dev libxi-dev libgl-dev
sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-w64-i686 gcc-mingw-w64-i686 libxinerama-dev libxcursor-dev libxi-dev libgl-dev
- name: Build makeheaders
run: |
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

+201 -13
View File
@@ -42,10 +42,10 @@ const BlockDef BLOCKS[] = {
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{ "cyan_block", R_Normal, B_Stone, 5, 0, 24},
BlockDef{ "magenta_block", R_Normal, B_Stone, 5, 0, 25},
BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 26},
BlockDef{ "black_block", R_Normal, B_Stone, 5, 0, 27},
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},
BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 27},
BlockDef{ "leaves", R_TranslucentAllSides, B_Grass, 1, 0, 28},
BlockDef{ "copper_ore", R_Normal, B_Stone, 7, 1, 5},
BlockDef{ "silver_ore", R_Normal, B_Stone, 7, 2, 6},
@@ -127,6 +127,36 @@ int GetSkyLight(World &world, int x, int y, int z) {
int skyLight = (light >> 12) & 0xF;
return skyLight;
}
int GetRLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return 0;
int locX = x % CHUNK_SIZE;
int locZ = z % CHUNK_SIZE;
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 >> 8) & 0xF;
return skyLight;
}
int GetGLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return 0;
int locX = x % CHUNK_SIZE;
int locZ = z % CHUNK_SIZE;
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 >> 4) & 0xF;
return skyLight;
}
int GetBLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return 0;
int locX = x % CHUNK_SIZE;
int locZ = z % CHUNK_SIZE;
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 & 0xF;
return skyLight;
}
Color GetLight(World &world, int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0};
int locX = x % CHUNK_SIZE;
@@ -135,8 +165,19 @@ Color GetLight(World &world, int x, int y, int z) {
int cz = z / CHUNK_SIZE;
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
int skyLight = ((light >> 12) & 0xF) * 16;
//return {((light >> 8) & 0xF) * 16 + skyLight, (light >> 4) * 16 + skyLight, (light & 0xF) * 16 + skyLight, 255};
return {skyLight, skyLight, skyLight, 255};
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);
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),
255
};
}
bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too!
return blockType == BLOCK_SAND;
@@ -244,7 +285,20 @@ void SetBlock(World &world, int x, int y, int z, int t) {
}
void SetLightChunk(Chunk *c, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) {
c->light[GetIndexChunk(x,y,z)] = sky << 12 | r << 8 | g << 4 | b;
int target = c->light[GetIndexChunk(x,y,z)];
if(sky > 0) {
target |= sky << 12;
}
if(r > 0) {
target |= r << 8;
}
if(g > 0) {
target |= g << 4;
}
if(b > 0) {
target |= b;
}
c->light[GetIndexChunk(x,y,z)] = target;
}
void SetLight(World &world, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) {
if(CheckOOBWorld(x, y, z)) { return; }
@@ -553,6 +607,9 @@ void RebuildOpaqueMask(Chunk &chunk) {
}
void RebuildLighting(World &world, int startX, int startZ) {
const Vector3I dirs[6] = { (Vector3I){ 1, 0, 0 }, (Vector3I){ -1, 0, 0 }, (Vector3I){ 0, 1, 0 }, (Vector3I){ 0,-1, 0 }, (Vector3I){ 0, 0, 1 }, (Vector3I){ 0, 0,-1 } };
// sky lighting
std::queue<LightNode> nodes;
for (int cx = -1; cx <= 1; cx++)
@@ -566,24 +623,20 @@ void RebuildLighting(World &world, int startX, int startZ) {
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;
for (int _y = WORLD_HEIGHT; _y >= y; _y--)
{
SetLight(world, pos.x, _y, pos.z, 15, 0, 0, 0);
}
LightNode node{pos, 15};
SetLight(world, pos.x, pos.y, pos.z, 15, 0, 0, 0);
nodes.push(node);
}
}
}
}
const Vector3I dirs[6] = { (Vector3I){ 1, 0, 0 }, (Vector3I){ -1, 0, 0 }, (Vector3I){ 0, 1, 0 }, (Vector3I){ 0,-1, 0 }, (Vector3I){ 0, 0, 1 }, (Vector3I){ 0, 0,-1 } };
while (!nodes.empty()) {
std::cout << nodes.size() << std::endl;
LightNode node = nodes.front();
nodes.pop();
@@ -595,7 +648,7 @@ void RebuildLighting(World &world, int startX, int startZ) {
};
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
if (GetBlock(world, newPos.x, newPos.y, newPos.z) != BLOCK_AIR) continue;
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
int newValue = node.value - 1;
if (newValue <= 0) continue;
@@ -605,6 +658,141 @@ void RebuildLighting(World &world, int startX, int startZ) {
nodes.push({ newPos, newValue });
}
}
// red lighting
std::queue<LightNode> nodesR;
for (int cx = -1; cx <= 1; cx++)
{
for (int cz = -1; cz <= 1; cz++) {
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
{
int x, y, z;
GetXYZFromIndex(i, &x, &y, &z);
if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 18 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15};
nodesR.push(node);
}
}
}
while (!nodesR.empty()) {
std::cout << nodesR.size() << std::endl;
LightNode node = nodesR.front();
nodesR.pop();
for (int i = 0; i < 6; i++) {
Vector3I newPos = {
node.position.x + dirs[i].x,
node.position.y + dirs[i].y,
node.position.z + dirs[i].z
};
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 (GetRLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
SetLight(world, newPos.x, newPos.y, newPos.z, 0, newValue, 0, 0);
nodesR.push({ newPos, newValue });
}
}
// green lighting
std::queue<LightNode> nodesG;
for (int cx = -1; cx <= 1; cx++)
{
for (int cz = -1; cz <= 1; cz++) {
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
{
int x, y, z;
GetXYZFromIndex(i, &x, &y, &z);
if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 19 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15};
nodesG.push(node);
}
}
}
while (!nodesG.empty()) {
std::cout << nodesG.size() << std::endl;
LightNode node = nodesG.front();
nodesG.pop();
for (int i = 0; i < 6; i++) {
Vector3I newPos = {
node.position.x + dirs[i].x,
node.position.y + dirs[i].y,
node.position.z + dirs[i].z
};
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 (GetGLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, newValue, 0);
nodesG.push({ newPos, newValue });
}
}
// blue lighting
std::queue<LightNode> nodesB;
for (int cx = -1; cx <= 1; cx++)
{
for (int cz = -1; cz <= 1; cz++) {
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
{
int x, y, z;
GetXYZFromIndex(i, &x, &y, &z);
if (CheckOOBWorld(x, y, z)) continue;
if(chunk.blocks[i] != 20 && chunk.blocks[i] != 21) continue;
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
std::cout << pos.y << std::endl;
LightNode node{pos, 15};
nodesB.push(node);
}
}
}
while (!nodesB.empty()) {
std::cout << nodesB.size() << std::endl;
LightNode node = nodesB.front();
nodesB.pop();
for (int i = 0; i < 6; i++) {
Vector3I newPos = {
node.position.x + dirs[i].x,
node.position.y + dirs[i].y,
node.position.z + dirs[i].z
};
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 (GetBLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, 0, newValue);
nodesB.push({ newPos, newValue });
}
}
}
#ifndef SERVER
//Generates an opaque CRD (ChunkRenderData). Outputs the CRD.
+8 -5
View File
@@ -78,7 +78,7 @@
#define DEFAULT_FONT_SIZE 16
#define TPS 30.0
#define TPS_DIV 1.0 / TPS
#define RENDER_DISTANCE 2
#define RENDER_DISTANCE 5
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
#define MAX_HP 100
#define PATH_APPEND "resources/"
@@ -307,6 +307,9 @@ extern const BlockDef BLOCKS[];
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);
int GetRLight(World&world,int x,int y,int z);
int GetGLight(World&world,int x,int y,int z);
int GetBLight(World&world,int x,int y,int z);
Color GetLight(World&world,int x,int y,int z);
bool CanTick(int blockType);
bool GetCloud(int x,int z);
@@ -463,10 +466,10 @@ inline void unpack6(uint8_t v,bool *b0,bool *b1,bool *b2,bool *b3,bool *b4,bool
*b5 = (v >> 5) & 1;
};
inline void GetXYZFromIndex(int index,int *x,int *y,int *z){
*x = index & 15;
int tmp = index << 4;
*z = tmp & 15;
*y = tmp << 4;
*y = index / (CHUNK_SIZE * CHUNK_SIZE);
int rem = index % (CHUNK_SIZE * CHUNK_SIZE);
*z = rem / CHUNK_SIZE;
*x = rem % CHUNK_SIZE;
};
inline int GetIndexChunk(int x,int y,int z){
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
+6 -5
View File
@@ -20,14 +20,15 @@ inline void unpack6(uint8_t v, bool *b0, bool *b1, bool *b2, bool *b3, bool *b4,
*b5 = (v >> 5) & 1;
}
inline void GetXYZFromIndex(int index, int *x, int *y, int *z) {
*x = index & 15;
int tmp = index << 4;
*z = tmp & 15;
*y = tmp << 4;
inline void GetXYZFromIndex(int index, int* x, int* y, int* z) {
*y = index / (CHUNK_SIZE * CHUNK_SIZE);
int rem = index % (CHUNK_SIZE * CHUNK_SIZE);
*z = rem / CHUNK_SIZE;
*x = rem % CHUNK_SIZE;
}
inline int GetIndexChunk(int x, int y, int z) {
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
return x + CHUNK_SIZE * (z + CHUNK_SIZE * y);
+1 -1
View File
@@ -102,7 +102,7 @@
#define TPS 30.0
#define TPS_DIV 1.0 / TPS
//Rendering
#define RENDER_DISTANCE 2
#define RENDER_DISTANCE 5
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
//Game stuff