Fix lighting for non 0 minX/Y/Z and non 1 maxX/Z blocks.

This commit is contained in:
UnknownShadow200 2015-12-24 12:43:56 +11:00
parent 1852330219
commit 2b3326197f
5 changed files with 62 additions and 42 deletions

View File

@ -11,7 +11,7 @@ namespace ClassicalSharp {
public Vector3[] MaxBB = new Vector3[BlocksCount]; public Vector3[] MaxBB = new Vector3[BlocksCount];
void InitBoundingBoxes() { void InitBoundingBoxes() {
for( int i = 0; i < 256; i++ ) { for( int i = 0; i < BlocksCount; i++ ) {
if( IsSprite[i] ) { if( IsSprite[i] ) {
MinBB[i] = new Vector3( 2.50f/16f, 0, 2.50f/16f ); MinBB[i] = new Vector3( 2.50f/16f, 0, 2.50f/16f );
MaxBB[i] = new Vector3( 13.5f/16f, 1, 13.5f/16f ); MaxBB[i] = new Vector3( 13.5f/16f, 1, 13.5f/16f );
@ -22,8 +22,20 @@ namespace ClassicalSharp {
} }
} }
internal void InitLightOffsets() {
for( int tile = 0; tile < BlocksCount; tile++ ) {
int flags = 0xFF;
Vector3 min = MinBB[tile], max = MaxBB[tile];
if( min.X != 0 ) flags &= ~(1 << TileSide.Left);
if( max.X != 1 ) flags &= ~(1 << TileSide.Right);
if( min.Z != 0 ) flags &= ~(1 << TileSide.Front);
if( max.Z != 1 ) flags &= ~(1 << TileSide.Back);
LightOffset[tile] = (byte)flags;
}
}
public void RecalculateSpriteBB( FastBitmap fastBmp ) { public void RecalculateSpriteBB( FastBitmap fastBmp ) {
for( int i = 0; i < 256; i++ ) { for( int i = 0; i < BlocksCount; i++ ) {
if( IsSprite[i] ) RecalculateBB( i, fastBmp ); if( IsSprite[i] ) RecalculateBB( i, fastBmp );
} }
} }

View File

@ -46,6 +46,8 @@ namespace ClassicalSharp {
public bool[] CullWithNeighbours = new bool[BlocksCount]; public bool[] CullWithNeighbours = new bool[BlocksCount];
public byte[] LightOffset = new byte[BlocksCount];
public const byte MaxDefinedCpeBlock = (byte)Block.StoneBrick; public const byte MaxDefinedCpeBlock = (byte)Block.StoneBrick;
public const int CpeBlocksCount = MaxDefinedCpeBlock + 1; public const int CpeBlocksCount = MaxDefinedCpeBlock + 1;
public const byte MaxDefinedBlock = byte.MaxValue; public const byte MaxDefinedBlock = byte.MaxValue;
@ -100,6 +102,7 @@ namespace ClassicalSharp {
InitBoundingBoxes(); InitBoundingBoxes();
InitSounds(); InitSounds();
InitLightOffsets();
SetupCullingCache(); SetupCullingCache();
} }

View File

@ -140,7 +140,7 @@
<Compile Include="Audio\AudioPlayer.Sounds.cs" /> <Compile Include="Audio\AudioPlayer.Sounds.cs" />
<Compile Include="Audio\Soundboard.cs" /> <Compile Include="Audio\Soundboard.cs" />
<Compile Include="Blocks\Block.cs" /> <Compile Include="Blocks\Block.cs" />
<Compile Include="Blocks\BlockInfo.BoundingBox.cs" /> <Compile Include="Blocks\BlockInfo.BoundsBox.cs" />
<Compile Include="Blocks\BlockInfo.cs" /> <Compile Include="Blocks\BlockInfo.cs" />
<Compile Include="Blocks\BlockInfo.Culling.cs" /> <Compile Include="Blocks\BlockInfo.Culling.cs" />
<Compile Include="Blocks\BlockInfo.Atlas.cs" /> <Compile Include="Blocks\BlockInfo.Atlas.cs" />

View File

@ -144,6 +144,7 @@ namespace ClassicalSharp {
fullBright = info.FullBright[tile]; fullBright = info.FullBright[tile];
isTranslucent = info.IsTranslucent[tile]; isTranslucent = info.IsTranslucent[tile];
lightFlags = info.LightOffset[tile];
if( leftCount != 0 ) if( leftCount != 0 )
DrawLeftFace( leftCount ); DrawLeftFace( leftCount );
@ -274,7 +275,9 @@ namespace ClassicalSharp {
chunkIndex++; chunkIndex++;
countIndex += TileSide.Sides; countIndex += TileSide.Sides;
int max = chunkSize - xx; int max = chunkSize - xx;
while( count < max && x < width && CanStretch( tile, chunkIndex, x, y, z, face ) ) { bool stretchTile = info.CanStretch[tile * TileSide.Sides + face];
while( count < max && x < width && stretchTile && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
counts[countIndex] = 0; counts[countIndex] = 0;
count++; count++;
x++; x++;
@ -290,7 +293,9 @@ namespace ClassicalSharp {
chunkIndex += extChunkSize; chunkIndex += extChunkSize;
countIndex += chunkSize * TileSide.Sides; countIndex += chunkSize * TileSide.Sides;
int max = chunkSize - zz; int max = chunkSize - zz;
while( count < max && z < length && CanStretch( tile, chunkIndex, x, y, z, face ) ) { bool stretchTile = info.CanStretch[tile * TileSide.Sides + face];
while( count < max && z < length && stretchTile && CanStretch( tile, chunkIndex, x, y, z, face ) ) {
counts[countIndex] = 0; counts[countIndex] = 0;
count++; count++;
z++; z++;

View File

@ -10,6 +10,7 @@ namespace ClassicalSharp {
TerrainAtlas1D atlas; TerrainAtlas1D atlas;
int arraysCount = 0; int arraysCount = 0;
bool fullBright; bool fullBright;
int lightFlags;
void TerrainAtlasChanged( object sender, EventArgs e ) { void TerrainAtlasChanged( object sender, EventArgs e ) {
int newArraysCount = game.TerrainAtlas1D.TexIds.Length; int newArraysCount = game.TerrainAtlas1D.TexIds.Length;
@ -64,30 +65,25 @@ namespace ClassicalSharp {
bool CanStretch( byte initialTile, int chunkIndex, int x, int y, int z, int face ) { bool CanStretch( byte initialTile, int chunkIndex, int x, int y, int z, int face ) {
byte tile = chunk[chunkIndex]; byte tile = chunk[chunkIndex];
return tile == initialTile && info.CanStretch[tile * TileSide.Sides + face] && return tile == initialTile && !info.IsFaceHidden( tile, GetNeighbour( chunkIndex, face ), face )
!info.IsFaceHidden( tile, GetNeighbour( chunkIndex, face ), face ) && && (fullBright || IsLit( X, Y, Z, face, initialTile ) == IsLit( x, y, z, face, tile ) );
( IsLit( X, Y, Z, face ) == IsLit( x, y, z, face ) );
} }
bool IsLit( int x, int y, int z, int face ) { bool IsLit( int x, int y, int z, int face, byte type ) {
int offset = (info.LightOffset[type] >> face) & 1;
switch( face ) { switch( face ) {
case TileSide.Left: case TileSide.Left:
return fullBright || x <= 0 || y > map.heightmap[(z * width) + (x - 1)]; return x < offset || y > map.heightmap[(z * width) + (x - offset)];
case TileSide.Right: case TileSide.Right:
return fullBright || x >= maxX || y > map.heightmap[(z * width) + (x + 1)]; return x > (maxX - offset) || y > map.heightmap[(z * width) + (x + offset)];
case TileSide.Front: case TileSide.Front:
return fullBright || z <= 0 || y > map.heightmap[((z - 1) * width) + x]; return z < offset || y > map.heightmap[((z - offset) * width) + x];
case TileSide.Back: case TileSide.Back:
return fullBright || z >= maxZ || y > map.heightmap[((z + 1) * width) + x]; return z > (maxZ - offset) || y > map.heightmap[((z + offset) * width) + x];
case TileSide.Bottom: case TileSide.Bottom:
return fullBright || y <= 0 || (y - 1) > map.heightmap[(z * width) + x]; return y <= 0 || (y - 1) > map.heightmap[(z * width) + x];
case TileSide.Top: case TileSide.Top:
return fullBright || y >= maxY || y > map.heightmap[(z * width) + x]; return y >= maxY || y > map.heightmap[(z * width) + x];
} }
return true; return true;
} }
@ -169,13 +165,14 @@ namespace ClassicalSharp {
int texId = info.textures[tile * TileSide.Sides + TileSide.Left]; int texId = info.textures[tile * TileSide.Sides + TileSide.Left];
int i = texId / elementsPerAtlas1D; int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize; float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
int offset = (lightFlags >> TileSide.Left) & 1;
float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f; float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize; float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f; float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White : FastColour col = fullBright ? FastColour.White :
X > 0 ? (Y > map.heightmap[(Z * width) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide; X >= offset ? (Y > map.heightmap[(Z * width) + (X - offset)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z2 + (count - 1), u2, v1, col ); part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z2 + (count - 1), u2, v1, col );
part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z1, u1, v1, col ); part.vertices[part.vIndex.left++] = new VertexPos3fTex2fCol4b( x1, y2, z1, u1, v1, col );
@ -187,13 +184,14 @@ namespace ClassicalSharp {
int texId = info.textures[tile * TileSide.Sides + TileSide.Right]; int texId = info.textures[tile * TileSide.Sides + TileSide.Right];
int i = texId / elementsPerAtlas1D; int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize; float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
int offset = (lightFlags >> TileSide.Right) & 1;
float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f; float u1 = minBB.Z, u2 = (maxBB.Z + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize; float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f; float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White : FastColour col = fullBright ? FastColour.White :
X < maxX ? (Y > map.heightmap[(Z * width) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide; X <= (maxX - offset) ? (Y > map.heightmap[(Z * width) + (X + offset)] ? map.SunlightXSide : map.ShadowlightXSide) : map.SunlightXSide;
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z1, u2, v1, col ); part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z1, u2, v1, col );
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z2 + (count - 1), u1, v1, col ); part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y2, z2 + (count - 1), u1, v1, col );
@ -201,35 +199,18 @@ namespace ClassicalSharp {
part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y1, z1, u2, v2, col ); part.vertices[part.vIndex.right++] = new VertexPos3fTex2fCol4b( x2, y1, z1, u2, v2, col );
} }
void DrawBackFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Back];
int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White :
Z < maxZ ? (Y > map.heightmap[((Z + 1) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z2, u2, v1, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y2, z2, u1, v1, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y1, z2, u1, v2, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z2, u2, v2, col );
}
void DrawFrontFace( int count ) { void DrawFrontFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Front]; int texId = info.textures[tile * TileSide.Sides + TileSide.Front];
int i = texId / elementsPerAtlas1D; int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize; float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
int offset = (lightFlags >> TileSide.Front) & 1;
float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f; float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize; float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f; float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White : FastColour col = fullBright ? FastColour.White :
Z > 0 ? (Y > map.heightmap[((Z - 1) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide; Z >= offset ? (Y > map.heightmap[((Z - offset) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z1, u1, v2, col ); part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z1, u1, v2, col );
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x1, y1, z1, u2, v2, col ); part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x1, y1, z1, u2, v2, col );
@ -237,6 +218,25 @@ namespace ClassicalSharp {
part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z1, u1, v1, col ); part.vertices[part.vIndex.front++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z1, u1, v1, col );
} }
void DrawBackFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Back];
int i = texId / elementsPerAtlas1D;
float vOrigin = (texId % elementsPerAtlas1D) * invVerElementSize;
int offset = (lightFlags >> TileSide.Back) & 1;
float u1 = minBB.X, u2 = (maxBB.X + (count - 1)) * 15.99f/16f;
float v1 = vOrigin + minBB.Y * invVerElementSize;
float v2 = vOrigin + maxBB.Y * invVerElementSize * 15.99f/16f;
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
FastColour col = fullBright ? FastColour.White :
Z <= (maxZ - offset) ? (Y > map.heightmap[((Z + offset) * width) + X] ? map.SunlightZSide : map.ShadowlightZSide) : map.SunlightZSide;
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y2, z2, u2, v1, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y2, z2, u1, v1, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x1, y1, z2, u1, v2, col );
part.vertices[part.vIndex.back++] = new VertexPos3fTex2fCol4b( x2 + (count - 1), y1, z2, u2, v2, col );
}
void DrawBottomFace( int count ) { void DrawBottomFace( int count ) {
int texId = info.textures[tile * TileSide.Sides + TileSide.Bottom]; int texId = info.textures[tile * TileSide.Sides + TileSide.Bottom];
int i = texId / elementsPerAtlas1D; int i = texId / elementsPerAtlas1D;