Optimise map rendering slightly. (memory side)

This commit is contained in:
UnknownShadow200 2015-06-15 19:15:58 +10:00
parent 32b37262b7
commit 274b742a25
4 changed files with 60 additions and 58 deletions

View File

@ -29,7 +29,7 @@ namespace ClassicalSharp {
bool BuildChunk( int x1, int y1, int z1 ) { bool BuildChunk( int x1, int y1, int z1 ) {
PreStretchTiles( x1, y1, z1 ); PreStretchTiles( x1, y1, z1 );
if( ReadChunkData( x1, y1, z1 ) ) return true; if( ReadChunkData( x1, y1, z1 ) ) return false;
Stretch( x1, y1, z1 ); Stretch( x1, y1, z1 );
PostStretchTiles( x1, y1, z1 ); PostStretchTiles( x1, y1, z1 );
@ -47,7 +47,7 @@ namespace ClassicalSharp {
} }
} }
} }
return false; return true;
} }
unsafe bool ReadChunkData( int x1, int y1, int z1 ) { unsafe bool ReadChunkData( int x1, int y1, int z1 ) {
@ -92,8 +92,13 @@ namespace ClassicalSharp {
return allAir || allSolid; return allAir || allSolid;
} }
public ChunkDrawInfo GetDrawInfo( int x, int y, int z ) { public bool GetDrawInfo( int x, int y, int z, ref ChunkPartInfo[] solidParts,
return BuildChunk( x, y, z ) ? null : GetChunkInfo( x, y, z ); ref ChunkPartInfo[] spriteParts, ref ChunkPartInfo[] translucentParts ) {
if( !BuildChunk( x, y, z ) )
return false;
GetChunkInfo( x, y, z, ref solidParts, ref spriteParts, ref translucentParts );
return true;
} }
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 ) {
@ -329,19 +334,6 @@ namespace ClassicalSharp {
} }
} }
public class ChunkDrawInfo {
public ChunkPartInfo[] SolidParts;
public ChunkPartInfo[] TranslucentParts;
public ChunkPartInfo[] SpriteParts;
public ChunkDrawInfo( int partsCount ) {
SolidParts = new ChunkPartInfo[partsCount];
TranslucentParts = new ChunkPartInfo[partsCount];
SpriteParts = new ChunkPartInfo[partsCount];
}
}
public struct ChunkPartInfo { public struct ChunkPartInfo {
public int VbId, IbId; public int VbId, IbId;

View File

@ -127,29 +127,32 @@ namespace ClassicalSharp {
( BlockInfo.BlockHeight( map.GetBlock( x, y, z ) ) == 1 ? y : y - 1 ); ( BlockInfo.BlockHeight( map.GetBlock( x, y, z ) ) == 1 ? y : y - 1 );
} }
ChunkDrawInfo GetChunkInfo( int x, int y, int z ) { void GetChunkInfo( int x, int y, int z, ref ChunkPartInfo[] solidParts,
ChunkDrawInfo info = new ChunkDrawInfo( arraysCount ); ref ChunkPartInfo[] spriteParts, ref ChunkPartInfo[] translucentParts ) {
for( int i = 0; i < arraysCount; i++ ) { for( int i = 0; i < arraysCount; i++ ) {
DrawInfo1D drawInfo = drawInfoBuffer[i]; DrawInfo1D info = drawInfoBuffer[i];
SetPartInfo( drawInfo.Solid, i, info.SolidParts ); SetPartInfo( info.Solid, i, ref solidParts );
SetPartInfo( drawInfo.Translucent, i, info.TranslucentParts ); SetPartInfo( info.Sprite, i, ref spriteParts );
SetPartInfo( drawInfo.Sprite, i, info.SpriteParts ); SetPartInfo( info.Translucent, i, ref translucentParts );
} }
return info;
} }
void SetPartInfo( DrawInfo1DPart part, int i, ChunkPartInfo[] parts ) { void SetPartInfo( DrawInfo1DPart part, int i, ref ChunkPartInfo[] parts ) {
if( part.iCount1 == 0 ) return;
ChunkPartInfo info = default( ChunkPartInfo ); ChunkPartInfo info = default( ChunkPartInfo );
if( part.iCount1 > 0 ) {
info.VbId = Graphics.InitVb( part.vertices1, VertexFormat.Pos3fTex2fCol4b, part.vCount1 ); info.VbId = Graphics.InitVb( part.vertices1, VertexFormat.Pos3fTex2fCol4b, part.vCount1 );
info.IbId = Graphics.InitIb( part.indices1, part.iCount1 ); info.IbId = Graphics.InitIb( part.indices1, part.iCount1 );
info.IndicesCount = part.iCount1; info.IndicesCount = part.iCount1;
}
if( part.iCount2 > 0 ) { if( part.iCount2 > 0 ) {
info.VbId2 = Graphics.InitVb( part.vertices2, VertexFormat.Pos3fTex2fCol4b, part.vCount2 ); info.VbId2 = Graphics.InitVb( part.vertices2, VertexFormat.Pos3fTex2fCol4b, part.vCount2 );
info.IbId2 = Graphics.InitIb( part.indices2, part.iCount2 ); info.IbId2 = Graphics.InitIb( part.indices2, part.iCount2 );
info.IndicesCount2 = part.iCount2; info.IndicesCount2 = part.iCount2;
} }
// Lazy initalize part arrays so we can save time in MapRenderer for chunks that only contain 1 or 2 part types.
if( parts == null )
parts = new ChunkPartInfo[arraysCount];
parts[i] = info; parts[i] = info;
} }

View File

@ -11,11 +11,12 @@ namespace ClassicalSharp {
class ChunkInfo { class ChunkInfo {
public short CentreX, CentreY, CentreZ; public short CentreX, CentreY, CentreZ;
public bool Visible = true; public bool Visible = true;
public bool Empty = false; public bool Empty = false;
public ChunkDrawInfo DrawInfo; public ChunkPartInfo[] SolidParts;
public ChunkPartInfo[] SpriteParts;
public ChunkPartInfo[] TranslucentParts;
public ChunkInfo( int x, int y, int z ) { public ChunkInfo( int x, int y, int z ) {
CentreX = (short)( x + 8 ); CentreX = (short)( x + 8 );
@ -111,19 +112,20 @@ namespace ClassicalSharp {
} }
void DeleteChunk( ChunkInfo info ) { void DeleteChunk( ChunkInfo info ) {
ChunkDrawInfo drawInfo = info.DrawInfo;
info.Empty = false; info.Empty = false;
if( drawInfo == null ) return; DeleteData( ref info.SolidParts );
DeleteData( ref info.SpriteParts );
for( int i = 0; i < drawInfo.SolidParts.Length; i++ ) { DeleteData( ref info.TranslucentParts );
Graphics.DeleteVb( drawInfo.SpriteParts[i].VbId );
Graphics.DeleteIb( drawInfo.SpriteParts[i].IbId );
Graphics.DeleteVb( drawInfo.TranslucentParts[i].VbId );
Graphics.DeleteIb( drawInfo.TranslucentParts[i].IbId );
Graphics.DeleteVb( drawInfo.SolidParts[i].VbId );
Graphics.DeleteIb( drawInfo.SolidParts[i].IbId );
} }
info.DrawInfo = null;
void DeleteData( ref ChunkPartInfo[] parts ) {
if( parts == null ) return;
for( int i = 0; i < parts.Length; i++ ) {
Graphics.DeleteVb( parts[i].VbId );
Graphics.DeleteIb( parts[i].IbId );
}
parts = null;
} }
void CreateChunkCache() { void CreateChunkCache() {
@ -262,14 +264,14 @@ namespace ClassicalSharp {
int distSqr = distances[i]; int distSqr = distances[i];
bool inRange = distSqr <= adjViewDistSqr; bool inRange = distSqr <= adjViewDistSqr;
if( info.DrawInfo == null ) { if( info.SolidParts == null && info.SpriteParts == null && info.TranslucentParts == null ) {
if( inRange && chunksUpdatedThisFrame < 4 ) { if( inRange && chunksUpdatedThisFrame < 4 ) {
Window.ChunkUpdates++; Window.ChunkUpdates++;
info.DrawInfo = builder.GetDrawInfo( info.CentreX - 8, info.CentreY - 8, info.CentreZ - 8 ); if( !builder.GetDrawInfo( info.CentreX - 8, info.CentreY - 8, info.CentreZ - 8,
if( info.DrawInfo == null ) { ref info.SolidParts, ref info.SpriteParts, ref info.TranslucentParts ) ) {
info.Empty = true; info.Empty = true;
} }
chunksUpdatedThisFrame++; chunksThisFrame++;
} }
} }
info.Visible = inRange && info.Visible = inRange &&
@ -277,14 +279,13 @@ namespace ClassicalSharp {
} }
} }
// TODO: there's probably a better way of doing this.
const DrawMode mode = DrawMode.Triangles; const DrawMode mode = DrawMode.Triangles;
void RenderSolidBatch( int batch ) { void RenderSolidBatch( int batch ) {
for( int i = 0; i < chunks.Length; i++ ) { for( int i = 0; i < chunks.Length; i++ ) {
ChunkInfo info = chunks[i]; ChunkInfo info = chunks[i];
if( info.DrawInfo == null || !info.Visible ) continue; if( info.SolidParts == null || !info.Visible ) continue;
ChunkPartInfo drawInfo = info.DrawInfo.SolidParts[batch]; ChunkPartInfo drawInfo = info.SolidParts[batch];
if( drawInfo.IndicesCount > 0 ) { if( drawInfo.IndicesCount > 0 ) {
Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount ); Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount );
Window.Vertices += drawInfo.IndicesCount; Window.Vertices += drawInfo.IndicesCount;
@ -299,9 +300,9 @@ namespace ClassicalSharp {
void RenderSpriteBatch( int batch ) { void RenderSpriteBatch( int batch ) {
for( int i = 0; i < chunks.Length; i++ ) { for( int i = 0; i < chunks.Length; i++ ) {
ChunkInfo info = chunks[i]; ChunkInfo info = chunks[i];
if( info.DrawInfo == null || !info.Visible ) continue; if( info.SpriteParts == null || !info.Visible ) continue;
ChunkPartInfo drawInfo = info.DrawInfo.SpriteParts[batch]; ChunkPartInfo drawInfo = info.SpriteParts[batch];
if( drawInfo.IndicesCount > 0 ) { if( drawInfo.IndicesCount > 0 ) {
Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount ); Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount );
Window.Vertices += drawInfo.IndicesCount; Window.Vertices += drawInfo.IndicesCount;
@ -312,9 +313,9 @@ namespace ClassicalSharp {
void RenderTranslucentBatch( int batch ) { void RenderTranslucentBatch( int batch ) {
for( int i = 0; i < chunks.Length; i++ ) { for( int i = 0; i < chunks.Length; i++ ) {
ChunkInfo info = chunks[i]; ChunkInfo info = chunks[i];
if( info.DrawInfo == null || !info.Visible ) continue; if( info.TranslucentParts == null || !info.Visible ) continue;
ChunkPartInfo drawInfo = info.DrawInfo.TranslucentParts[batch]; ChunkPartInfo drawInfo = info.TranslucentParts[batch];
if( drawInfo.IndicesCount > 0 ) { if( drawInfo.IndicesCount > 0 ) {
Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount ); Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount );
Window.Vertices += drawInfo.IndicesCount; Window.Vertices += drawInfo.IndicesCount;
@ -329,9 +330,9 @@ namespace ClassicalSharp {
void RenderTranslucentBatchNoAdd( int batch ) { void RenderTranslucentBatchNoAdd( int batch ) {
for( int i = 0; i < chunks.Length; i++ ) { for( int i = 0; i < chunks.Length; i++ ) {
ChunkInfo info = chunks[i]; ChunkInfo info = chunks[i];
if( info.DrawInfo == null || !info.Visible ) continue; if( info.TranslucentParts == null || !info.Visible ) continue;
ChunkPartInfo drawInfo = info.DrawInfo.TranslucentParts[batch]; ChunkPartInfo drawInfo = info.TranslucentParts[batch];
if( drawInfo.IndicesCount > 0 ) { if( drawInfo.IndicesCount > 0 ) {
Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount ); Graphics.DrawIndexedVbBatch( mode, drawInfo.VbId, drawInfo.IbId, drawInfo.IndicesCount );
if( drawInfo.IndicesCount2 > 0 ) { if( drawInfo.IndicesCount2 > 0 ) {

View File

@ -43,6 +43,12 @@ namespace ClassicalSharp {
using( Bitmap bmp = new Bitmap( elementSize, elementSize ) ) { using( Bitmap bmp = new Bitmap( elementSize, elementSize ) ) {
using( FastBitmap dst = new FastBitmap( bmp, true ) ) { using( FastBitmap dst = new FastBitmap( bmp, true ) ) {
Utils.MovePortion( x * elementSize, y * elementSize, 0, 0, atlas, dst, elementSize ); Utils.MovePortion( x * elementSize, y * elementSize, 0, 0, atlas, dst, elementSize );
for( int xxx = 0; xxx < 2; xxx++ ) {
for( int yyy = 0; yyy < 2; yyy++ ) {
Console.WriteLine( dst.GetPixel( xxx, yyy ) & 0xFF );
}
}
return graphics.LoadTexture( dst ); return graphics.LoadTexture( dst );
} }
} }