mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-30 09:03:21 -04:00
Make light occlusion take block shape and other properties into account
This commit is contained in:
parent
e4b259aaad
commit
3a2613fa56
@ -142,7 +142,7 @@ static void LightQueue_Resize(struct LightQueue* queue) {
|
||||
}
|
||||
capacity = queue->capacity * 2;
|
||||
if (capacity < 32) capacity = 32;
|
||||
entries = (IVec3*)Mem_Alloc(capacity, sizeof(IVec3), "Block queue");
|
||||
entries = (IVec3*)Mem_Alloc(capacity, sizeof(IVec3), "Light queue");
|
||||
for (i = 0; i < queue->count; i++) {
|
||||
idx = (queue->head + i) & queue->mask;
|
||||
entries[i] = queue->entries[idx];
|
||||
@ -203,7 +203,7 @@ static void ModernLighting_InitPalette(void) {
|
||||
float blockLerp;
|
||||
cc_uint8 R, G, B;
|
||||
|
||||
defaultBlockLight = PackedCol_Make(255, 238, 204, 255); /* A very mildly orange tinted light color */
|
||||
defaultBlockLight = PackedCol_Make(150, 112, 79, 255); /* A very mildly orange tinted light color */
|
||||
darkestShadow = PackedCol_Lerp(Env.ShadowCol, 0, 0.75f); /* Use a darkened version of shadow color as the darkest color in sun ramp */
|
||||
|
||||
for (sunLevel = 0; sunLevel < MODERN_LIGHTING_LEVELS; sunLevel++) {
|
||||
@ -217,7 +217,7 @@ static void ModernLighting_InitPalette(void) {
|
||||
sunColor = PackedCol_Lerp(darkestShadow, Env.ShadowCol, sunLevel / (float)(MODERN_LIGHTING_LEVELS - 2));
|
||||
}
|
||||
blockLerp = blockLevel / (float)(MODERN_LIGHTING_LEVELS - 1);
|
||||
blockLerp *= blockLerp;
|
||||
//blockLerp *= blockLerp;
|
||||
blockLerp *= (MATH_PI / 2);
|
||||
blockLerp = Math_Cos(blockLerp);
|
||||
blockColor = PackedCol_Lerp(0, defaultBlockLight, 1 - blockLerp);
|
||||
@ -293,6 +293,19 @@ static cc_uint8 GetBlocklight(int x, int y, int z) {
|
||||
return chunkLightingData[chunkIndex][localIndex] & MODERN_LIGHTING_MAX_LEVEL;
|
||||
}
|
||||
|
||||
static cc_bool CanLightPass(BlockID thisBlock, Face face) {
|
||||
/* If it's not opaque and it doesn't block light, or it's fullbright, we can always pass through */
|
||||
if ((Blocks.Draw[thisBlock] > DRAW_OPAQUE && !Blocks.BlocksLight[thisBlock]) || Blocks.FullBright[thisBlock]) { return true; }
|
||||
/* Light can always pass through leaves and water */
|
||||
if (Blocks.Draw[thisBlock] == DRAW_TRANSPARENT_THICK || Blocks.Draw[thisBlock] == DRAW_TRANSLUCENT) { return true; }
|
||||
|
||||
/* Light can never pass through a block that's full sized and blocks light */
|
||||
/* We can assume a block is full sized if none of the LightOffset flags are 0 */
|
||||
if (Blocks.BlocksLight[thisBlock] && Blocks.LightOffset[thisBlock] == 0xFF) { return false; }
|
||||
|
||||
/* Is stone's face hidden by thisBlock? */
|
||||
return !Block_IsFaceHidden(BLOCK_STONE, thisBlock, face);
|
||||
}
|
||||
static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
|
||||
SetBlocklight(blockLight, x, y, z);
|
||||
@ -308,11 +321,14 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
Platform_Log1("but there were still %i entries left...", &lightQueue.capacity);
|
||||
return;
|
||||
}
|
||||
BlockID thisBlock = World_GetBlock(curNode.X, curNode.Y, curNode.Z);
|
||||
|
||||
|
||||
curNode.X--;
|
||||
if (curNode.X > 0 &&
|
||||
curBlockLight-1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_XMAX) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_XMIN) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight-1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
@ -322,7 +338,8 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
curNode.X += 2;
|
||||
if (curNode.X < World.MaxX &&
|
||||
curBlockLight - 1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_XMIN) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_XMAX) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight - 1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
@ -334,7 +351,8 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
curNode.Y--;
|
||||
if (curNode.Y > 0 &&
|
||||
curBlockLight - 1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_YMAX) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_YMIN) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight - 1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
@ -344,7 +362,8 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
curNode.Y += 2;
|
||||
if (curNode.Y < World.MaxY &&
|
||||
curBlockLight - 1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_YMIN) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_YMAX) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight - 1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
@ -352,11 +371,12 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
LightQueue_Enqueue(&lightQueue, entry);
|
||||
}
|
||||
curNode.Y--;
|
||||
|
||||
|
||||
curNode.Z--;
|
||||
if (curNode.Z > 0 &&
|
||||
curBlockLight - 1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_ZMAX) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_ZMIN) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight - 1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
@ -366,20 +386,14 @@ static void CalcBlockLight(cc_uint8 blockLight, int x, int y, int z) {
|
||||
curNode.Z += 2;
|
||||
if (curNode.Z < World.MaxZ &&
|
||||
curBlockLight - 1 > 1 &&
|
||||
!Blocks.BlocksLight[World_GetBlock(curNode.X, curNode.Y, curNode.Z)] &&
|
||||
CanLightPass(thisBlock, FACE_ZMIN) &&
|
||||
CanLightPass(World_GetBlock(curNode.X, curNode.Y, curNode.Z), FACE_ZMAX) &&
|
||||
GetBlocklight(curNode.X, curNode.Y, curNode.Z) < curBlockLight - 1
|
||||
) {
|
||||
SetBlocklight(curBlockLight - 1, curNode.X, curNode.Y, curNode.Z);
|
||||
IVec3 entry = { curNode.X, curNode.Y, curNode.Z };
|
||||
LightQueue_Enqueue(&lightQueue, entry);
|
||||
}
|
||||
|
||||
//Step 5: Look at all neighbouring voxels to that node.
|
||||
// if that node is in bounds of the world
|
||||
// AND if light is allowed to spread to that node,
|
||||
// AND if that node's light level is 2 or more levels less than the current node,
|
||||
// then set their light level to the current nodes light level - 1,
|
||||
// and then add that node to the queue.
|
||||
}
|
||||
}
|
||||
static void CalculateChunkLightingSelf(int chunkIndex, int cx, int cy, int cz) {
|
||||
@ -406,10 +420,6 @@ static void CalculateChunkLightingSelf(int chunkIndex, int cx, int cy, int cz) {
|
||||
|
||||
BlockID curBlock = World_GetBlock(x, y, z);
|
||||
if (Blocks.FullBright[curBlock]) {
|
||||
|
||||
//String_InitArray(msg, msgBuffer);
|
||||
//String_Format3(&msg, "found bright block at %i %i %i", &x, &y, &z);
|
||||
//Chat_Add(&msg);
|
||||
CalcBlockLight(15, x, y, z);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user