Simplify updating atlases, move TextureAtlas1D to TerrainAtlas1D.

This commit is contained in:
UnknownShadow200 2015-05-27 19:47:09 +10:00
parent f5a55c50b8
commit f191885115
7 changed files with 50 additions and 41 deletions

View File

@ -152,7 +152,7 @@
<Compile Include="Utils\Camera.cs" /> <Compile Include="Utils\Camera.cs" />
<Compile Include="Utils\FastBitmap.cs" /> <Compile Include="Utils\FastBitmap.cs" />
<Compile Include="Utils\FastColour.cs" /> <Compile Include="Utils\FastColour.cs" />
<Compile Include="Utils\TextureAtlas1D.cs" /> <Compile Include="Utils\TerrainAtlas1D.cs" />
<Compile Include="Utils\TerrainAtlas2D.cs" /> <Compile Include="Utils\TerrainAtlas2D.cs" />
<Compile Include="Utils\TextureRectangle.cs" /> <Compile Include="Utils\TextureRectangle.cs" />
<Compile Include="Utils\UnsafeString.cs" /> <Compile Include="Utils\UnsafeString.cs" />

View File

@ -29,8 +29,7 @@ namespace ClassicalSharp {
public BlockInfo BlockInfo; public BlockInfo BlockInfo;
public double accumulator; public double accumulator;
public TerrainAtlas2D TerrainAtlas; public TerrainAtlas2D TerrainAtlas;
public TextureAtlas1D TerrainAtlas1D; public TerrainAtlas1D TerrainAtlas1D;
public int[] TerrainAtlas1DTexIds;
public SkinType DefaultPlayerSkinType; public SkinType DefaultPlayerSkinType;
public int ChunkUpdates; public int ChunkUpdates;
@ -95,17 +94,10 @@ namespace ClassicalSharp {
public int MouseSensitivity = 30; public int MouseSensitivity = 30;
void LoadAtlas( Bitmap bmp ) { void LoadAtlas( Bitmap bmp ) {
// Cleanup old atlas if applicable. TerrainAtlas1D.Dispose();
if( TerrainAtlas1DTexIds != null ) {
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) {
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
}
}
TerrainAtlas.GraphicsApi = Graphics;
TerrainAtlas.Dispose(); TerrainAtlas.Dispose();
TerrainAtlas.UpdateState( bmp ); TerrainAtlas.UpdateState( bmp );
int size = Math.Min( 2048, Graphics.MaxTextureDimensions ); TerrainAtlas1D.UpdateState( TerrainAtlas );
TerrainAtlas1DTexIds = TerrainAtlas1D.CreateFrom2DAtlas( Graphics, TerrainAtlas, size );
} }
public void ChangeTerrainAtlas( Bitmap newAtlas ) { public void ChangeTerrainAtlas( Bitmap newAtlas ) {
@ -127,8 +119,8 @@ namespace ClassicalSharp {
AsyncDownloader = new AsyncDownloader( skinServer ); AsyncDownloader = new AsyncDownloader( skinServer );
PrintGraphicsInfo(); PrintGraphicsInfo();
Bitmap terrainBmp = new Bitmap( "terrain.png" ); Bitmap terrainBmp = new Bitmap( "terrain.png" );
TerrainAtlas1D = new TextureAtlas1D(); TerrainAtlas1D = new TerrainAtlas1D( Graphics );
TerrainAtlas = new TerrainAtlas2D(); TerrainAtlas = new TerrainAtlas2D( Graphics );
LoadAtlas( terrainBmp ); LoadAtlas( terrainBmp );
BlockInfo = new BlockInfo(); BlockInfo = new BlockInfo();
BlockInfo.Init(); BlockInfo.Init();
@ -284,9 +276,7 @@ namespace ClassicalSharp {
fpsScreen.Dispose(); fpsScreen.Dispose();
SelectionManager.Dispose(); SelectionManager.Dispose();
TerrainAtlas.Dispose(); TerrainAtlas.Dispose();
for( int i = 0; i < TerrainAtlas1DTexIds.Length; i++ ) { TerrainAtlas1D.Dispose();
Graphics.DeleteTexture( ref TerrainAtlas1DTexIds[i] );
}
ModelCache.Dispose(); ModelCache.Dispose();
for( int i = 0; i < NetPlayers.Length; i++ ) { for( int i = 0; i < NetPlayers.Length; i++ ) {
if( NetPlayers[i] != null ) { if( NetPlayers[i] != null ) {

View File

@ -6,12 +6,12 @@ namespace ClassicalSharp {
public partial class ChunkMeshBuilder { public partial class ChunkMeshBuilder {
DrawInfo1D[] drawInfoBuffer; DrawInfo1D[] drawInfoBuffer;
TextureAtlas1D atlas; TerrainAtlas1D atlas;
int arraysCount = 0; int arraysCount = 0;
const int maxIndices = 65536; const int maxIndices = 65536;
void TerrainAtlasChanged( object sender, EventArgs e ) { void TerrainAtlasChanged( object sender, EventArgs e ) {
int newArraysCount = Window.TerrainAtlas1DTexIds.Length; int newArraysCount = Window.TerrainAtlas1D.TexIds.Length;
if( arraysCount > 0 && arraysCount != newArraysCount ) { if( arraysCount > 0 && arraysCount != newArraysCount ) {
Array.Resize( ref drawInfoBuffer, newArraysCount ); Array.Resize( ref drawInfoBuffer, newArraysCount );
for( int i = arraysCount; i < drawInfoBuffer.Length; i++ ) { for( int i = arraysCount; i < drawInfoBuffer.Length; i++ ) {
@ -157,7 +157,7 @@ namespace ClassicalSharp {
void PreStretchTiles( int x1, int y1, int z1 ) { void PreStretchTiles( int x1, int y1, int z1 ) {
invVerElementSize = Window.TerrainAtlas1D.invElementSize; invVerElementSize = Window.TerrainAtlas1D.invElementSize;
arraysCount = Window.TerrainAtlas1DTexIds.Length; arraysCount = Window.TerrainAtlas1D.TexIds.Length;
atlas = Window.TerrainAtlas1D; atlas = Window.TerrainAtlas1D;
if( drawInfoBuffer == null ) { if( drawInfoBuffer == null ) {

View File

@ -50,7 +50,7 @@ namespace ClassicalSharp {
public MapRenderer( Game window ) { public MapRenderer( Game window ) {
Window = window; Window = window;
_1Dcount = window.TerrainAtlas1DTexIds.Length; _1Dcount = window.TerrainAtlas1D.TexIds.Length;
builder = new ChunkMeshBuilder( window ); builder = new ChunkMeshBuilder( window );
Graphics = window.Graphics; Graphics = window.Graphics;
elementsPerBitmap = window.TerrainAtlas1D.elementsPerBitmap; elementsPerBitmap = window.TerrainAtlas1D.elementsPerBitmap;
@ -83,7 +83,7 @@ namespace ClassicalSharp {
} }
void TerrainAtlasChanged( object sender, EventArgs e ) { void TerrainAtlasChanged( object sender, EventArgs e ) {
_1Dcount = Window.TerrainAtlas1DTexIds.Length; _1Dcount = Window.TerrainAtlas1D.TexIds.Length;
bool fullResetRequired = elementsPerBitmap != Window.TerrainAtlas1D.elementsPerBitmap; bool fullResetRequired = elementsPerBitmap != Window.TerrainAtlas1D.elementsPerBitmap;
if( fullResetRequired ) { if( fullResetRequired ) {
Refresh(); Refresh();
@ -197,6 +197,7 @@ namespace ClassicalSharp {
if( chunks == null ) return; if( chunks == null ) return;
UpdateSortOrder(); UpdateSortOrder();
UpdateChunks(); UpdateChunks();
int[] texIds = Window.TerrainAtlas1D.TexIds;
// Render solid and fully transparent to fill depth buffer. // Render solid and fully transparent to fill depth buffer.
// These blocks are treated as having an alpha value of either none or full. // These blocks are treated as having an alpha value of either none or full.
@ -205,12 +206,12 @@ namespace ClassicalSharp {
Graphics.AlphaTest = true; Graphics.AlphaTest = true;
Graphics.FaceCulling = true; Graphics.FaceCulling = true;
for( int batch = 0; batch < _1Dcount; batch++ ) { for( int batch = 0; batch < _1Dcount; batch++ ) {
Graphics.Bind2DTexture( Window.TerrainAtlas1DTexIds[batch] ); Graphics.Bind2DTexture( texIds[batch] );
RenderSolidBatch( batch ); RenderSolidBatch( batch );
} }
Graphics.FaceCulling = false; Graphics.FaceCulling = false;
for( int batch = 0; batch < _1Dcount; batch++ ) { for( int batch = 0; batch < _1Dcount; batch++ ) {
Graphics.Bind2DTexture( Window.TerrainAtlas1DTexIds[batch] ); Graphics.Bind2DTexture( texIds[batch] );
RenderSpriteBatch( batch ); RenderSpriteBatch( batch );
} }
Graphics.AlphaTest = false; Graphics.AlphaTest = false;
@ -235,7 +236,7 @@ namespace ClassicalSharp {
Graphics.Texturing = true; Graphics.Texturing = true;
Graphics.ColourMask( true, true, true, true ); Graphics.ColourMask( true, true, true, true );
for( int batch = 0; batch < _1Dcount; batch++ ) { for( int batch = 0; batch < _1Dcount; batch++ ) {
Graphics.Bind2DTexture( Window.TerrainAtlas1DTexIds[batch] ); Graphics.Bind2DTexture( texIds[batch] );
RenderTranslucentBatch( batch ); RenderTranslucentBatch( batch );
} }
Graphics.DepthTestFunc( CompareFunc.Less ); Graphics.DepthTestFunc( CompareFunc.Less );

View File

@ -4,11 +4,17 @@ using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp { namespace ClassicalSharp {
public class TextureAtlas1D { public class TerrainAtlas1D : IDisposable {
int usedElementsPerAtlas1D; int usedElementsPerAtlas1D;
internal int elementsPerBitmap; internal int elementsPerBitmap;
public float invElementSize; public float invElementSize;
public int[] TexIds;
IGraphicsApi graphics;
public TerrainAtlas1D( IGraphicsApi graphics ) {
this.graphics = graphics;
}
public TextureRectangle GetTexRec( int texId, int uCount, out int index ) { public TextureRectangle GetTexRec( int texId, int uCount, out int index ) {
index = texId / usedElementsPerAtlas1D; index = texId / usedElementsPerAtlas1D;
@ -24,21 +30,22 @@ namespace ClassicalSharp {
return texId % usedElementsPerAtlas1D; return texId % usedElementsPerAtlas1D;
} }
public int[] CreateFrom2DAtlas( IGraphicsApi graphics, TerrainAtlas2D atlas2D, int maxVerSize ) { public void UpdateState( TerrainAtlas2D atlas2D ) {
int maxVerSize = Math.Min( 2048, graphics.MaxTextureDimensions );
int verElements = maxVerSize / atlas2D.elementSize; int verElements = maxVerSize / atlas2D.elementSize;
int totalElements = atlas2D.UsedRowsCount * TerrainAtlas2D.ElementsPerRow; int totalElements = atlas2D.UsedRowsCount * TerrainAtlas2D.ElementsPerRow;
int elemSize = atlas2D.elementSize; int elemSize = atlas2D.elementSize;
int atlasesCount = totalElements / verElements + ( totalElements % verElements != 0 ? 1 : 0 ); int atlasesCount = totalElements / verElements + ( totalElements % verElements != 0 ? 1 : 0 );
usedElementsPerAtlas1D = Math.Min( verElements, totalElements ); // in case verElements > totalElements usedElementsPerAtlas1D = Math.Min( verElements, totalElements );
int atlas1DHeight = Utils.NextPowerOf2( usedElementsPerAtlas1D * atlas2D.elementSize ); int atlas1DHeight = Utils.NextPowerOf2( usedElementsPerAtlas1D * atlas2D.elementSize );
int index = 0; int index = 0;
int[] texIds = new int[atlasesCount]; TexIds = new int[atlasesCount];
Utils.LogDebug( "Loaded new atlas: {0} bmps, {1} per bmp", atlasesCount, usedElementsPerAtlas1D ); Utils.LogDebug( "Loaded new atlas: {0} bmps, {1} per bmp", atlasesCount, usedElementsPerAtlas1D );
using( FastBitmap atlas = new FastBitmap( atlas2D.AtlasBitmap, true ) ) { using( FastBitmap atlas = new FastBitmap( atlas2D.AtlasBitmap, true ) ) {
for( int i = 0; i < texIds.Length; i++ ) { for( int i = 0; i < TexIds.Length; i++ ) {
Bitmap atlas1d = new Bitmap( atlas2D.elementSize, atlas1DHeight ); Bitmap atlas1d = new Bitmap( atlas2D.elementSize, atlas1DHeight );
using( FastBitmap dst = new FastBitmap( atlas1d, true ) ) { using( FastBitmap dst = new FastBitmap( atlas1d, true ) ) {
for( int y_1D = 0; y_1D < usedElementsPerAtlas1D; y_1D++ ) { for( int y_1D = 0; y_1D < usedElementsPerAtlas1D; y_1D++ ) {
@ -47,14 +54,21 @@ namespace ClassicalSharp {
Utils.MovePortion( x * elemSize, y * elemSize, 0, y_1D * elemSize, atlas, dst, elemSize ); Utils.MovePortion( x * elemSize, y * elemSize, 0, y_1D * elemSize, atlas, dst, elemSize );
index++; index++;
} }
texIds[i] = graphics.LoadTexture( dst ); TexIds[i] = graphics.LoadTexture( dst );
} }
atlas1d.Dispose(); atlas1d.Dispose();
} }
} }
elementsPerBitmap = atlas1DHeight / atlas2D.elementSize; elementsPerBitmap = atlas1DHeight / atlas2D.elementSize;
invElementSize = 1f / elementsPerBitmap; invElementSize = 1f / elementsPerBitmap;
return texIds; }
public void Dispose() {
if( TexIds != null ) {
for( int i = 0; i < TexIds.Length; i++ ) {
graphics.DeleteTexture( ref TexIds[i] );
}
}
} }
} }
} }

View File

@ -20,15 +20,19 @@ namespace ClassicalSharp {
public readonly int UsedRowsCount = 5; public readonly int UsedRowsCount = 5;
public Bitmap AtlasBitmap; public Bitmap AtlasBitmap;
public int elementSize; public int elementSize;
public IGraphicsApi GraphicsApi;
public int TexId; public int TexId;
IGraphicsApi graphics;
public TerrainAtlas2D( IGraphicsApi graphics ) {
this.graphics = graphics;
}
public void UpdateState( Bitmap bmp ) { public void UpdateState( Bitmap bmp ) {
AtlasBitmap = bmp; AtlasBitmap = bmp;
elementSize = bmp.Width >> 4; elementSize = bmp.Width >> 4;
using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) { using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) {
MakeOptimisedTexture( fastBmp ); MakeOptimisedTexture( fastBmp );
TexId = GraphicsApi.LoadTexture( fastBmp ); TexId = graphics.LoadTexture( fastBmp );
} }
} }
@ -39,7 +43,7 @@ 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 );
return GraphicsApi.LoadTexture( dst ); return graphics.LoadTexture( dst );
} }
} }
} }
@ -55,7 +59,7 @@ namespace ClassicalSharp {
if( AtlasBitmap != null ) { if( AtlasBitmap != null ) {
AtlasBitmap.Dispose(); AtlasBitmap.Dispose();
} }
GraphicsApi.DeleteTexture( ref TexId ); graphics.DeleteTexture( ref TexId );
} }
static ushort[] rowFlags = { 0xFFFF, 0xFFEE, 0xFFE0, 0xFFE0, 0xFFFF, 0xFA00 }; static ushort[] rowFlags = { 0xFFFF, 0xFFEE, 0xFFE0, 0xFFE0, 0xFFFF, 0xFA00 };