Slightly optimise ChunkMeshBuilder, fix lava not being fully lit on all tile sides.

This commit is contained in:
UnknownShadow200 2015-09-01 16:33:05 +10:00
parent d9166bbf93
commit db800f3b32
3 changed files with 58 additions and 79 deletions

View File

@ -12,6 +12,7 @@ namespace ClassicalSharp {
internal bool[] isLiquid = new bool[BlocksCount]; internal bool[] isLiquid = new bool[BlocksCount];
internal float[] heights = new float[BlocksCount]; internal float[] heights = new float[BlocksCount];
internal bool[] blocksLight = new bool[BlocksCount]; internal bool[] blocksLight = new bool[BlocksCount];
internal bool[] emitsLight = new bool[BlocksCount];
public const byte MaxDefinedBlock = (byte)Block.StoneBrick; public const byte MaxDefinedBlock = (byte)Block.StoneBrick;
public const byte BlocksCount = MaxDefinedBlock + 1; public const byte BlocksCount = MaxDefinedBlock + 1;
@ -41,6 +42,7 @@ namespace ClassicalSharp {
SetIsSprite( Block.Rope, Block.Fire ); SetIsSprite( Block.Rope, Block.Fire );
SetBlockHeight( 8 / 16f, Block.CobblestoneSlab ); SetBlockHeight( 8 / 16f, Block.CobblestoneSlab );
SetBlockHeight( 2 / 16f, Block.Snow ); SetBlockHeight( 2 / 16f, Block.Snow );
SetEmitsLight( true, Block.Lava, Block.StillLava );
SetupCullingCache(); SetupCullingCache();
} }
@ -101,20 +103,24 @@ namespace ClassicalSharp {
} }
} }
void SetEmitsLight( bool emits, params Block[] ids ) {
for( int i = 0; i < ids.Length; i++ ) {
emitsLight[(int)ids[i]] = emits;
}
}
/// <summary> Gets whether the given block id is opaque/not see through. </summary> /// <summary> Gets whether the given block id is opaque/not see through. </summary>
public bool IsOpaque( byte id ) { public bool IsOpaque( byte id ) {
return isOpaque[id]; return isOpaque[id];
} }
/// <summary> Gets whether the given block id is opaque/not see through, /// <summary> Gets whether the given block id is opaque/not see through, and occupies a full block. </summary>
/// and occupies a full block. </summary>
public bool IsFullAndOpaque( byte id ) { public bool IsFullAndOpaque( byte id ) {
return isOpaque[id] && heights[id] == 1; return isOpaque[id] && heights[id] == 1;
} }
/// <summary> Gets whether the given block id is transparent/fully see through. </summary> /// <summary> Gets whether the given block id is transparent/fully see through. </summary>
/// <remarks> Note that these blocks's alpha values are treated as either 'fully see through' /// <remarks> Alpha values are treated as either 'fully see through' or 'fully solid'. </remarks>
/// or 'fully solid'. </remarks>
public bool IsTransparent( byte id ) { public bool IsTransparent( byte id ) {
return isTransparent[id]; return isTransparent[id];
} }
@ -125,8 +131,7 @@ namespace ClassicalSharp {
} }
/// <summary> Gets whether the given block id is translucent/partially see through. </summary> /// <summary> Gets whether the given block id is translucent/partially see through. </summary>
/// <remarks> Note that these blocks's colour values are blended into both /// <remarks>Colour values are blended into both the transparent and opaque blocks behind them. </remarks>
/// the transparent and opaque blocks behind them. </remarks>
public bool IsTranslucent( byte id ) { public bool IsTranslucent( byte id ) {
return isTranslucent[id]; return isTranslucent[id];
} }
@ -136,16 +141,18 @@ namespace ClassicalSharp {
return blocksLight[id]; return blocksLight[id];
} }
/// <summary> Gets whether the given block id is a sprite. <br/> /// <summary> Gets whether the given block id is a sprite. (flowers, saplings, fire, etc) </summary>
/// (flowers, saplings, fire, etc) </summary>
public bool IsSprite( byte id ) { public bool IsSprite( byte id ) {
return isSprite[id]; return isSprite[id];
} }
/// <summary> Gets whether the given block id is a liquid. <br/> /// <summary> Gets whether the given block id is a liquid. (water or lava) </summary>
/// (water or lava) </summary>
public bool IsLiquid( byte id ) { public bool IsLiquid( byte id ) {
return isLiquid[id]; return isLiquid[id];
} }
public bool EmitsLight( byte id ) {
return emitsLight[id];
}
} }
} }

View File

@ -111,42 +111,39 @@ namespace ClassicalSharp {
public void RenderTile( int chunkIndex, int xx, int yy, int zz, int x, int y, int z ) { public void RenderTile( int chunkIndex, int xx, int yy, int zz, int x, int y, int z ) {
X = x; Y = y; Z = z; X = x; Y = y; Z = z;
blockHeight = -1;
int index = ( ( yy << 8 ) + ( zz << 4 ) + xx ) * TileSide.Sides; int index = ( ( yy << 8 ) + ( zz << 4 ) + xx ) * TileSide.Sides;
int count = 0;
if( BlockInfo.IsSprite( tile ) ) { if( BlockInfo.isSprite[tile] ) {
count = counts[index]; int count = counts[index];
if( count != 0 ) { if( count != 0 ) {
blockHeight = BlockInfo.heights[tile];
DrawSprite( count ); DrawSprite( count );
} }
return; return;
} }
count = counts[index + TileSide.Left]; int leftCount = counts[index++], rightCount = counts[index++],
if( count != 0 ) { frontCount = counts[index++], backCount = counts[index++],
DrawLeftFace( count ); bottomCount = counts[index++], topCount = counts[index++];
} if( leftCount == 0 && rightCount == 0 && frontCount == 0 &&
count = counts[index + TileSide.Right]; backCount == 0 && bottomCount == 0 && topCount == 0 ) return;
if( count != 0 ) {
DrawRightFace( count ); emitsLight = BlockInfo.emitsLight[tile];
} blockHeight = BlockInfo.heights[tile];
count = counts[index + TileSide.Front]; isTranslucent = BlockInfo.isTranslucent[tile];
if( count != 0 ) {
DrawFrontFace( count ); if( leftCount != 0 )
} DrawLeftFace( leftCount );
count = counts[index + TileSide.Back]; if( rightCount != 0 )
if( count != 0 ) { DrawRightFace( rightCount );
DrawBackFace( count ); if( frontCount != 0 )
} DrawFrontFace( frontCount );
count = counts[index + TileSide.Bottom]; if( backCount != 0 )
if( count != 0 ) { DrawBackFace( backCount );
DrawBottomFace( count ); if( bottomCount != 0 )
} DrawBottomFace( bottomCount );
count = counts[index + TileSide.Top]; if( topCount != 0 )
if( count != 0 ) { DrawTopFace( topCount );
DrawTopFace( count );
}
} }
void Stretch( int x1, int y1, int z1 ) { void Stretch( int x1, int y1, int z1 ) {
@ -178,6 +175,7 @@ namespace ClassicalSharp {
} }
} else { } else {
X = x; Y = y; Z = z; X = x; Y = y; Z = z;
emitsLight = BlockInfo.emitsLight[tile];
TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, 0, TileSide.Left, -1 ); TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, 0, TileSide.Left, -1 );
TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, maxX, TileSide.Right, 1 ); TestAndStretchZ( zz, countIndex, tile, chunkIndex, x, maxX, TileSide.Right, 1 );
TestAndStretchX( xx, countIndex, tile, chunkIndex, z, 0, TileSide.Front, -extChunkSize ); TestAndStretchX( xx, countIndex, tile, chunkIndex, z, 0, TileSide.Front, -extChunkSize );

View File

@ -9,6 +9,7 @@ namespace ClassicalSharp {
DrawInfo[] drawInfoNormal, drawInfoTranslucent; DrawInfo[] drawInfoNormal, drawInfoTranslucent;
TerrainAtlas1D atlas; TerrainAtlas1D atlas;
int arraysCount = 0; int arraysCount = 0;
bool emitsLight;
void TerrainAtlasChanged( object sender, EventArgs e ) { void TerrainAtlasChanged( object sender, EventArgs e ) {
int newArraysCount = Window.TerrainAtlas1D.TexIds.Length; int newArraysCount = Window.TerrainAtlas1D.TexIds.Length;
@ -70,22 +71,22 @@ namespace ClassicalSharp {
bool IsLit( int x, int y, int z, int face ) { bool IsLit( int x, int y, int z, int face ) {
switch( face ) { switch( face ) {
case TileSide.Left: case TileSide.Left:
return x <= 0 || y > map.heightmap[( z * width ) + (x - 1)]; return emitsLight || x <= 0 || y > map.heightmap[( z * width ) + (x - 1)];
case TileSide.Right: case TileSide.Right:
return x >= maxX || y > map.heightmap[( z * width ) + (x + 1)]; return emitsLight || x >= maxX || y > map.heightmap[( z * width ) + (x + 1)];
case TileSide.Front: case TileSide.Front:
return z <= 0 || y > map.heightmap[( (z - 1) * width ) + x]; return emitsLight || z <= 0 || y > map.heightmap[( (z - 1) * width ) + x];
case TileSide.Back: case TileSide.Back:
return z >= maxZ || y > map.heightmap[( (z + 1) * width ) + x]; return emitsLight || z >= maxZ || y > map.heightmap[( (z + 1) * width ) + x];
case TileSide.Bottom: case TileSide.Bottom:
return y <= 0 || (y - 1) > map.heightmap[( z * width ) + x]; return emitsLight || y <= 0 || (y - 1) > map.heightmap[( z * width ) + x];
case TileSide.Top: case TileSide.Top:
return y >= maxY || (y + 1) > map.heightmap[( z * width ) + x]; return emitsLight || y >= maxY || (y + 1) > map.heightmap[( z * width ) + x];
} }
return true; return true;
} }
@ -166,12 +167,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Left );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = X > 0 ? ( Y > map.heightmap[( Z * width ) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide ) FastColour col = X > 0 ? ( emitsLight || Y > map.heightmap[( Z * width ) + (X - 1)] ? map.SunlightXSide : map.ShadowlightXSide )
: map.SunlightXSide; : map.SunlightXSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
if( blockHeight != 1 ) { if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * invVerElementSize; rec.V2 = rec.V1 + blockHeight * invVerElementSize;
} }
@ -187,12 +184,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = X < maxX ? ( Y > map.heightmap[( Z * width ) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide ) FastColour col = X < maxX ? ( emitsLight || Y > map.heightmap[( Z * width ) + (X + 1)] ? map.SunlightXSide : map.ShadowlightXSide )
: map.SunlightXSide; : map.SunlightXSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
if( blockHeight != 1 ) { if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * invVerElementSize; rec.V2 = rec.V1 + blockHeight * invVerElementSize;
} }
@ -208,12 +201,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Back );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Z < maxZ ? ( Y > map.heightmap[( (Z + 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide ) FastColour col = Z < maxZ ? ( emitsLight || Y > map.heightmap[( (Z + 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
: map.SunlightZSide; : map.SunlightZSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
if( blockHeight != 1 ) { if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * invVerElementSize; rec.V2 = rec.V1 + blockHeight * invVerElementSize;
} }
@ -229,12 +218,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Front );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Z > 0 ? ( Y > map.heightmap[( (Z - 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide ) FastColour col = Z > 0 ? ( emitsLight || Y > map.heightmap[( (Z - 1) * width ) + X] ? map.SunlightZSide : map.ShadowlightZSide )
: map.SunlightZSide; : map.SunlightZSide;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
if( blockHeight != 1 ) { if( blockHeight != 1 ) {
rec.V2 = rec.V1 + blockHeight * invVerElementSize; rec.V2 = rec.V1 + blockHeight * invVerElementSize;
} }
@ -250,12 +235,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Bottom );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y > 0 ? ( (Y - 1) > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom ) FastColour col = Y > 0 ? ( emitsLight || (Y - 1) > map.heightmap[( Z * width ) + X] ? map.SunlightYBottom : map.ShadowlightYBottom )
: map.SunlightYBottom; : map.SunlightYBottom;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
part.vertices[part.vIndex.bottom++] = new VertexPos3fTex2fCol4b( X + count, Y, Z + 1, rec.U2, rec.V2, col ); part.vertices[part.vIndex.bottom++] = new VertexPos3fTex2fCol4b( X + count, Y, Z + 1, rec.U2, rec.V2, col );
@ -268,12 +249,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Top );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y < maxY ? ( (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight ) FastColour col = Y < maxY ? ( emitsLight || (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )
: map.Sunlight; : map.Sunlight;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
isTranslucent = BlockInfo.IsTranslucent( tile );
}
DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i]; DrawInfo part = isTranslucent ? drawInfoTranslucent[i] : drawInfoNormal[i];
part.vertices[part.vIndex.top++] = new VertexPos3fTex2fCol4b( X + count, Y + blockHeight, Z, rec.U2, rec.V1, col ); part.vertices[part.vIndex.top++] = new VertexPos3fTex2fCol4b( X + count, Y + blockHeight, Z, rec.U2, rec.V1, col );
@ -286,11 +263,8 @@ namespace ClassicalSharp {
int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right ); int texId = BlockInfo.GetOptimTextureLoc( tile, TileSide.Right );
int i; int i;
TextureRectangle rec = atlas.GetTexRec( texId, count, out i ); TextureRectangle rec = atlas.GetTexRec( texId, count, out i );
FastColour col = Y < maxY ? ( (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight ) FastColour col = Y < maxY ? ( emitsLight || (Y + 1) > map.heightmap[( Z * width ) + X] ? map.Sunlight : map.Shadowlight )
: map.Sunlight; : map.Sunlight;
if( blockHeight == -1 ) {
blockHeight = BlockInfo.BlockHeight( tile );
}
DrawInfo part = drawInfoNormal[i]; DrawInfo part = drawInfoNormal[i];
// Draw stretched Z axis // Draw stretched Z axis