Optimise map rendering - we keep track of which 1D texture atlases actually have any chunks in the world using them at all (in addition to the test on visible chunks), thus we can skip entire rows.

This commit is contained in:
UnknownShadow200 2016-04-13 17:40:09 +10:00
parent 19af48ca3a
commit 4dca01a619
4 changed files with 42 additions and 19 deletions

View File

@ -52,20 +52,15 @@ namespace ClassicalSharp {
bool underline = args.Font.Style == FontStyle.Underline; bool underline = args.Font.Style == FontStyle.Underline;
if( args.UseShadow ) { if( args.UseShadow ) {
int offset = ShadowOffset( args.Font.Size ); int offset = ShadowOffset( args.Font.Size );
int shadowX = x + offset, shadowY = y + offset; DrawPart( dst, ref args, x + offset, y + offset, true );
if( underline ) DrawUnderline( dst, x + offset, 0, ref args, true );
DrawPart( dst, ref args, ref shadowX, shadowY, true );
if( underline )
DrawUnderline( dst, x + offset, 0, ref args, true );
} }
int orignX = x; DrawPart( dst, ref args, x, y, false );
DrawPart( dst, ref args, ref x, y, false ); if( underline ) DrawUnderline( dst, x, -2, ref args, false );
if( underline )
DrawUnderline( dst, orignX, -2, ref args, false );
} }
void DrawPart( FastBitmap dst, ref DrawTextArgs args, ref int x, int y, bool shadowCol ) { void DrawPart( FastBitmap dst, ref DrawTextArgs args, int x, int y, bool shadowCol ) {
FastColour col = shadowCol ? FastColour.Black : FastColour.White; FastColour col = shadowCol ? FastColour.Black : FastColour.White;
FastColour lastCol = col; FastColour lastCol = col;
int xMul = args.Font.Style == FontStyle.Italic ? 1 : 0; int xMul = args.Font.Style == FontStyle.Italic ? 1 : 0;

View File

@ -16,6 +16,7 @@ namespace ClassicalSharp.Renderers {
api.AlphaTest = true; api.AlphaTest = true;
for( int batch = 0; batch < _1DUsed; batch++ ) { for( int batch = 0; batch < _1DUsed; batch++ ) {
if( totalUsed[batch] <= 0 ) continue;
if( pendingNormal[batch] || usedNormal[batch] ) { if( pendingNormal[batch] || usedNormal[batch] ) {
api.BindTexture( texIds[batch] ); api.BindTexture( texIds[batch] );
RenderNormalBatch( batch ); RenderNormalBatch( batch );
@ -38,6 +39,7 @@ namespace ClassicalSharp.Renderers {
api.AlphaBlending = false; api.AlphaBlending = false;
api.ColourWrite = false; api.ColourWrite = false;
for( int batch = 0; batch < _1DUsed; batch++ ) { for( int batch = 0; batch < _1DUsed; batch++ ) {
if( totalUsed[batch] <= 0 ) continue;
if( pendingTranslucent[batch] || usedTranslucent[batch] ) { if( pendingTranslucent[batch] || usedTranslucent[batch] ) {
RenderTranslucentBatchDepthPass( batch ); RenderTranslucentBatchDepthPass( batch );
pendingTranslucent[batch] = false; pendingTranslucent[batch] = false;
@ -51,6 +53,7 @@ namespace ClassicalSharp.Renderers {
api.DepthWrite = false; // we already calculated depth values in depth pass api.DepthWrite = false; // we already calculated depth values in depth pass
for( int batch = 0; batch < _1DUsed; batch++ ) { for( int batch = 0; batch < _1DUsed; batch++ ) {
if( totalUsed[batch] <= 0 ) continue;
if( !usedTranslucent[batch] ) continue; if( !usedTranslucent[batch] ) continue;
api.BindTexture( texIds[batch] ); api.BindTexture( texIds[batch] );
RenderTranslucentBatch( batch ); RenderTranslucentBatch( batch );

View File

@ -41,10 +41,12 @@ namespace ClassicalSharp.Renderers {
Vector3I chunkPos = new Vector3I( int.MaxValue, int.MaxValue, int.MaxValue ); Vector3I chunkPos = new Vector3I( int.MaxValue, int.MaxValue, int.MaxValue );
int elementsPerBitmap = 0; int elementsPerBitmap = 0;
bool[] usedTranslucent, usedNormal, pendingTranslucent, pendingNormal; bool[] usedTranslucent, usedNormal, pendingTranslucent, pendingNormal;
int[] totalUsed;
public MapRenderer( Game game ) { public MapRenderer( Game game ) {
this.game = game; this.game = game;
_1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, game.BlockInfo ); _1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, game.BlockInfo );
totalUsed = new int[game.TerrainAtlas1D.TexIds.Length];
RecalcBooleans( true ); RecalcBooleans( true );
builder = new ChunkMeshBuilder( game ); builder = new ChunkMeshBuilder( game );
@ -108,11 +110,10 @@ namespace ClassicalSharp.Renderers {
void TerrainAtlasChanged( object sender, EventArgs e ) { void TerrainAtlasChanged( object sender, EventArgs e ) {
bool refreshRequired = elementsPerBitmap != game.TerrainAtlas1D.elementsPerBitmap; bool refreshRequired = elementsPerBitmap != game.TerrainAtlas1D.elementsPerBitmap;
if( refreshRequired )
Refresh();
elementsPerBitmap = game.TerrainAtlas1D.elementsPerBitmap; elementsPerBitmap = game.TerrainAtlas1D.elementsPerBitmap;
_1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, game.BlockInfo ); _1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, game.BlockInfo );
if( refreshRequired ) Refresh();
RecalcBooleans( true ); RecalcBooleans( true );
} }
@ -125,6 +126,9 @@ namespace ClassicalSharp.Renderers {
void OnNewMap( object sender, EventArgs e ) { void OnNewMap( object sender, EventArgs e ) {
game.ChunkUpdates = 0; game.ChunkUpdates = 0;
ClearChunkCache(); ClearChunkCache();
for( int i = 0; i < totalUsed.Length; i++ )
totalUsed[i] = 0;
chunks = null; chunks = null;
unsortedChunks = null; unsortedChunks = null;
chunkPos = new Vector3I( int.MaxValue, int.MaxValue, int.MaxValue ); chunkPos = new Vector3I( int.MaxValue, int.MaxValue, int.MaxValue );
@ -174,6 +178,7 @@ namespace ClassicalSharp.Renderers {
if( chunks == null ) return; if( chunks == null ) return;
for( int i = 0; i < chunks.Length; i++ ) for( int i = 0; i < chunks.Length; i++ )
DeleteChunk( chunks[i] ); DeleteChunk( chunks[i] );
totalUsed = new int[game.TerrainAtlas1D.TexIds.Length];
} }
void DeleteChunk( ChunkInfo info ) { void DeleteChunk( ChunkInfo info ) {
@ -185,11 +190,11 @@ namespace ClassicalSharp.Renderers {
} }
void DeleteData( ref ChunkPartInfo[] parts ) { void DeleteData( ref ChunkPartInfo[] parts ) {
DecrementUsed( parts );
if( parts == null ) return; if( parts == null ) return;
for( int i = 0; i < parts.Length; i++ ) { for( int i = 0; i < parts.Length; i++ )
api.DeleteVb( parts[i].VbId ); api.DeleteVb( parts[i].VbId );
}
parts = null; parts = null;
} }
@ -334,9 +339,29 @@ namespace ClassicalSharp.Renderers {
builder.GetDrawInfo( info.CentreX - 8, info.CentreY - 8, info.CentreZ - 8, builder.GetDrawInfo( info.CentreX - 8, info.CentreY - 8, info.CentreZ - 8,
ref info.NormalParts, ref info.TranslucentParts, ref info.OcclusionFlags ); ref info.NormalParts, ref info.TranslucentParts, ref info.OcclusionFlags );
if( info.NormalParts == null && info.TranslucentParts == null ) if( info.NormalParts == null && info.TranslucentParts == null ) {
info.Empty = true; info.Empty = true;
} else {
IncrementUsed( info.NormalParts );
IncrementUsed( info.TranslucentParts );
}
chunkUpdates++; chunkUpdates++;
} }
void IncrementUsed( ChunkPartInfo[] parts ) {
if( parts == null ) return;
for( int i = 0; i < parts.Length; i++ ) {
if( parts[i].IndicesCount == 0 ) continue;
totalUsed[i]++;
}
}
void DecrementUsed( ChunkPartInfo[] parts ) {
if( parts == null ) return;
for( int i = 0; i < parts.Length; i++ ) {
if( parts[i].IndicesCount == 0 ) continue;
totalUsed[i]--;
}
}
} }
} }