From 0fe78fdf3b8dd3bd677c5dabb4fdb8d02eafad61 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 4 Aug 2015 08:33:00 +1000 Subject: [PATCH] Use indexed drawing and stackalloc in StandardEnvRenderer. --- ClassicalSharp/Game/Game.cs | 4 + ClassicalSharp/GraphicsAPI/IGraphicsApi.cs | 22 ++ ClassicalSharp/GraphicsAPI/OpenGLApi.cs | 2 +- ClassicalSharp/Rendering/MapEnvRenderer.cs | 226 ++++++------------ ClassicalSharp/Rendering/MapRenderer.cs | 26 +- .../Rendering/StandardEnvRenderer.cs | 151 +++++------- ClassicalSharp/Utils/Utils.cs | 2 +- 7 files changed, 162 insertions(+), 271 deletions(-) diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 26bcdb691..dc8d8713a 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -45,6 +45,7 @@ namespace ClassicalSharp { public PickedPos SelectedPos = new PickedPos(); public ModelCache ModelCache; internal string skinServer, chatInInputBuffer; + internal int defaultIb; public bool CanUseThirdPersonCamera = true; FpsScreen fpsScreen; @@ -119,6 +120,7 @@ namespace ClassicalSharp { #else Graphics = new Direct3D9Api( this ); #endif + defaultIb = Graphics.MakeDefaultIb(); ModelCache = new ModelCache( this ); AsyncDownloader = new AsyncDownloader( skinServer ); PrintGraphicsInfo(); @@ -186,6 +188,7 @@ namespace ClassicalSharp { protected override void OnRenderFrame( FrameEventArgs e ) { Graphics.BeginFrame( this ); + Graphics.BindIb( defaultIb ); accumulator += e.Time; imageCheckAccumulator += e.Time; ticksAccumulator += e.Time; @@ -278,6 +281,7 @@ namespace ClassicalSharp { if( writer != null ) { writer.Close(); } + Graphics.DeleteIb( defaultIb ); Graphics.Dispose(); Utils2D.Dispose(); base.Dispose(); diff --git a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs index 8ec6001bb..f03657ce2 100644 --- a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs +++ b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs @@ -128,6 +128,9 @@ namespace ClassicalSharp.GraphicsAPI { public abstract void DrawIndexedVb( DrawMode mode, int indicesCount, int startVertex, int startIndex ); + /// Optimised version of DrawIndexedVb for VertexFormat.Pos3fTex2fCol4b + //public abstract void DrawIndexedVb( DrawMode mode, int indicesCount, int startVertex, int startIndex ); + protected static int[] strideSizes = { 20, 16, 24 }; public abstract void SetMatrixMode( MatrixType mode ); @@ -221,6 +224,25 @@ namespace ClassicalSharp.GraphicsAPI { DepthTest = true; AlphaBlending = false; } + + public unsafe int MakeDefaultIb() { + const int maxIndices = 65536 / 4 * 6; + int element = 0; + ushort* indices = stackalloc ushort[maxIndices]; + IntPtr ptr = (IntPtr)indices; + + for( int i = 0; i < maxIndices; i += 6 ) { + *indices++ = (ushort)( element + 0 ); + *indices++ = (ushort)( element + 1 ); + *indices++ = (ushort)( element + 2 ); + + *indices++ = (ushort)( element + 2 ); + *indices++ = (ushort)( element + 3 ); + *indices++ = (ushort)( element + 0 ); + element += 4; + } + return CreateIb( ptr, maxIndices ); + } } public enum VertexFormat { diff --git a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs index f2e19d24d..80320a550 100644 --- a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs +++ b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs @@ -280,7 +280,7 @@ namespace ClassicalSharp.GraphicsAPI { GL.BindBufferARB( BufferTarget.ElementArrayBuffer, ib ); } - const DrawElementsType indexType = DrawElementsType.UnsignedShort; + const DrawElementsType indexType = DrawElementsType.UnsignedShort; public override void DrawIndexedVb( DrawMode mode, int indicesCount, int startVertex, int startIndex ) { int offset = startVertex * VertexPos3fTex2fCol4b.Size; GL.VertexPointer( 3, PointerType.Float, 24, new IntPtr( offset ) ); diff --git a/ClassicalSharp/Rendering/MapEnvRenderer.cs b/ClassicalSharp/Rendering/MapEnvRenderer.cs index 37890d463..b4a195a42 100644 --- a/ClassicalSharp/Rendering/MapEnvRenderer.cs +++ b/ClassicalSharp/Rendering/MapEnvRenderer.cs @@ -5,7 +5,7 @@ using ClassicalSharp.GraphicsAPI; namespace ClassicalSharp { - public sealed class MapEnvRenderer : IDisposable { + public unsafe sealed class MapEnvRenderer : IDisposable { public Map Map; public Game Window; @@ -16,9 +16,9 @@ namespace ClassicalSharp { Map = Window.Map; } - int sidesVboId = -1, edgesVboId = -1; + int sidesVb = -1, edgesVb = -1; int edgeTexId, sideTexId; - int sidesVertices, edgesVertices, index; + int sidesIndices, edgesIndices; static readonly FastColour sidesCol = new FastColour( 128, 128, 128 ), edgesCol = FastColour.White; bool legacy = false; @@ -41,18 +41,20 @@ namespace ClassicalSharp { } public void Render( double deltaTime ) { - if( sidesVboId == -1 || edgesVboId == -1 ) return; + if( sidesVb == -1 || edgesVb == -1 ) return; Graphics.Texturing = true; Graphics.BindTexture( sideTexId ); Graphics.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); - Graphics.DrawVb( DrawMode.Triangles, sidesVboId, 0, sidesVertices ); + Graphics.BindVb( sidesVb ); + Graphics.DrawIndexedVb( DrawMode.Triangles, sidesIndices, 0, 0 ); // Do not draw water when we cannot see it. // Fixes 'depth bleeding through' issues with 16 bit depth buffers on large maps. if( Window.LocalPlayer.EyePosition.Y >= 0 ) { Graphics.AlphaBlending = true; Graphics.BindTexture( edgeTexId ); - Graphics.DrawVb( DrawMode.Triangles, edgesVboId, 0, edgesVertices ); + Graphics.BindVb( edgesVb ); + Graphics.DrawIndexedVb( DrawMode.Triangles, edgesIndices, 0, 0 ); Graphics.AlphaBlending = false; } Graphics.Texturing = false; @@ -67,22 +69,23 @@ namespace ClassicalSharp { Graphics.DeleteTexture( ref edgeTexId ); Graphics.DeleteTexture( ref sideTexId ); - Graphics.DeleteVb( sidesVboId ); - Graphics.DeleteVb( edgesVboId ); - sidesVboId = edgesVboId = -1; + Graphics.DeleteVb( sidesVb ); + Graphics.DeleteVb( edgesVb ); + sidesVb = edgesVb = -1; } void OnNewMap( object sender, EventArgs e ) { - Graphics.DeleteVb( sidesVboId ); - Graphics.DeleteVb( edgesVboId ); - sidesVboId = edgesVboId = -1; + Graphics.DeleteVb( sidesVb ); + Graphics.DeleteVb( edgesVb ); + sidesVb = edgesVb = -1; MakeTexture( ref edgeTexId, ref lastEdgeTexLoc, Map.EdgeBlock ); MakeTexture( ref sideTexId, ref lastSideTexLoc, Map.SidesBlock ); } void OnNewMapLoaded( object sender, EventArgs e ) { - RebuildSides(); - RebuildEdges(); + CalculateRects( Window.ViewDistance ); + RebuildSides( Map.GroundHeight, legacy ? 128 : 65536 ); + RebuildEdges( Map.WaterHeight, legacy ? 128 : 65536 ); } void EnvVariableChanged( object sender, EnvVariableEventArgs e ) { @@ -103,112 +106,50 @@ namespace ClassicalSharp { void ResetSidesAndEdges( object sender, EventArgs e ) { if( Window.Map.IsNotLoaded ) return; - RebuildSides(); - RebuildEdges(); + Graphics.DeleteVb( sidesVb ); + Graphics.DeleteVb( edgesVb ); + CalculateRects( Window.ViewDistance ); + RebuildSides( Map.GroundHeight, legacy ? 128 : 65536 ); + RebuildEdges( Map.WaterHeight, legacy ? 128 : 65536 ); } - void RebuildSides() { - index = 0; - Graphics.DeleteVb( sidesVboId ); - if( legacy ) { - RebuildSidesLegacy( Map.GroundHeight ); - } else { - RebuildSidesModern( Map.GroundHeight ); + void RebuildSides( int groundLevel, int axisSize ) { + sidesIndices = 0; + foreach( Rectangle rec in rects ) { + sidesIndices += Utils.CountIndices( rec.Width, rec.Height, axisSize ); // YPlanes outside } - } - - void RebuildEdges() { - index = 0; - Graphics.DeleteVb( edgesVboId ); - if( legacy ) { - RebuildEdgesLegacy( Map.WaterHeight ); - } else { - RebuildEdgesModern( Map.WaterHeight ); - } - } - - // |-----------| - // | 2 | - // |---*****---| - // | 3 *Map* 4 | - // | * * | - // |---*****---| - // | 1 | - // |-----------| - IEnumerable OutsideMap( int extent ) { - yield return new Rectangle( -extent, -extent, extent + Map.Width + extent, extent ); - yield return new Rectangle( -extent, Map.Length, extent + Map.Width + extent, extent ); - yield return new Rectangle( -extent, 0, extent, Map.Length ); - yield return new Rectangle( Map.Width, 0, extent, Map.Length ); - } - - #region Modern - - void RebuildSidesModern( int groundLevel ) { - sidesVertices = 5 * 6 + 4 * 6; - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[sidesVertices]; + sidesIndices += Utils.CountIndices( Map.Width, Map.Length, axisSize ); // YPlane beneath map + sidesIndices += 2 * Utils.CountIndices( Map.Width, groundLevel, axisSize ); // ZPlanes + sidesIndices += 2 * Utils.CountIndices( Map.Length, groundLevel, axisSize ); // XPlanes + VertexPos3fTex2fCol4b* vertices = stackalloc VertexPos3fTex2fCol4b[sidesIndices / 6 * 4]; + IntPtr ptr = (IntPtr)vertices; - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - DrawYPlane( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, groundLevel, sidesCol, vertices ); + foreach( Rectangle rec in rects ) { + DrawY( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, groundLevel, axisSize, sidesCol, ref vertices ); } - DrawYPlane( 0, 0, Map.Width, Map.Length, 0, sidesCol, vertices ); - DrawZPlane( 0, 0, Map.Width, 0, groundLevel, sidesCol, vertices ); - DrawZPlane( Map.Length, 0, Map.Width, 0, groundLevel, sidesCol, vertices ); - DrawXPlane( 0, 0, Map.Length, 0, groundLevel, sidesCol, vertices ); - DrawXPlane( Map.Width, 0, Map.Length, 0, groundLevel, sidesCol, vertices ); - sidesVboId = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); + DrawY( 0, 0, Map.Width, Map.Length, 0, axisSize, sidesCol, ref vertices ); + DrawZ( 0, 0, Map.Width, 0, groundLevel, axisSize, sidesCol, ref vertices ); + DrawZ( Map.Length, 0, Map.Width, 0, groundLevel, axisSize, sidesCol, ref vertices ); + DrawX( 0, 0, Map.Length, 0, groundLevel, axisSize, sidesCol, ref vertices ); + DrawX( Map.Width, 0, Map.Length, 0, groundLevel, axisSize, sidesCol, ref vertices ); + sidesVb = Graphics.CreateVb( ptr, VertexFormat.Pos3fTex2fCol4b, sidesIndices / 6 * 4 ); } - void RebuildEdgesModern( int waterLevel ) { - edgesVertices = 4 * 6; - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[edgesVertices]; + void RebuildEdges( int waterLevel, int axisSize ) { + edgesIndices = 0; + foreach( Rectangle rec in rects ) { + edgesIndices += Utils.CountIndices( rec.Width, rec.Height, axisSize ); // YPlanes outside + } + VertexPos3fTex2fCol4b* vertices = stackalloc VertexPos3fTex2fCol4b[edgesIndices / 6 * 4]; + IntPtr ptr = (IntPtr)vertices; - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - DrawYPlane( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, waterLevel, edgesCol, vertices ); + foreach( Rectangle rec in rects ) { + DrawY( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, waterLevel, axisSize, edgesCol, ref vertices ); } - edgesVboId = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); + edgesVb = Graphics.CreateVb( ptr, VertexFormat.Pos3fTex2fCol4b, edgesIndices / 6 * 4 ); } - #endregion - - #region Legacy - - void RebuildSidesLegacy( int groundLevel ) { - sidesVertices = 0; - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - sidesVertices += Utils.CountVertices( rec.Width, rec.Height, axisSize ); // YPlanes outside - } - sidesVertices += Utils.CountVertices( Map.Width, Map.Length, axisSize ); // YPlane beneath map - sidesVertices += Utils.CountVertices( Map.Width, groundLevel, axisSize ) * 2; // ZPlanes - sidesVertices += Utils.CountVertices( Map.Length, groundLevel, axisSize ) * 2; // XPlanes - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[sidesVertices]; - - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - DrawYPlaneParts( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, groundLevel, sidesCol, vertices ); - } - DrawYPlaneParts( 0, 0, Map.Width, Map.Length, 0, sidesCol, vertices ); - DrawZPlaneParts( 0, 0, Map.Width, 0, groundLevel, sidesCol, vertices ); - DrawZPlaneParts( Map.Length, 0, Map.Width, 0, groundLevel, sidesCol, vertices ); - DrawXPlaneParts( 0, 0, Map.Length, 0, groundLevel, sidesCol, vertices ); - DrawXPlaneParts( Map.Width, 0, Map.Length, 0, groundLevel, sidesCol, vertices ); - sidesVboId = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); - } - - void RebuildEdgesLegacy( int waterLevel ) { - edgesVertices = 0; - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - edgesVertices += Utils.CountVertices( rec.Width, rec.Height, axisSize ); // YPlanes outside - } - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[edgesVertices]; - - foreach( Rectangle rec in OutsideMap( Window.ViewDistance ) ) { - DrawYPlaneParts( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, waterLevel, edgesCol, vertices ); - } - edgesVboId = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); - } - - const int axisSize = 128; - void DrawXPlaneParts( int x, int z1, int z2, int y1, int y2, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { + void DrawX( int x, int z1, int z2, int y1, int y2, int axisSize, FastColour col, ref VertexPos3fTex2fCol4b* vertices ) { int endZ = z2, endY = y2, startY = y1; for( ; z1 < endZ; z1 += axisSize ) { z2 = z1 + axisSize; @@ -217,12 +158,17 @@ namespace ClassicalSharp { for( ; y1 < endY; y1 += axisSize ) { y2 = y1 + axisSize; if( y2 > endY ) y2 = endY; - DrawXPlane( x, z1, z2, y1, y2, col, vertices ); + + TextureRectangle rec = new TextureRectangle( 0, 0, z2 - z1, y2 - y1 ); + *vertices++ = new VertexPos3fTex2fCol4b( x, y1, z1, rec.U1, rec.V1, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x, y2, z1, rec.U1, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x, y2, z2, rec.U2, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x, y1, z2, rec.U2, rec.V1, col ); } } } - void DrawZPlaneParts( int z, int x1, int x2, int y1, int y2, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { + void DrawZ( int z, int x1, int x2, int y1, int y2, int axisSize, FastColour col, ref VertexPos3fTex2fCol4b* vertices ) { int endX = x2, endY = y2, startY = y1; for( ; x1 < endX; x1 += axisSize ) { x2 = x1 + axisSize; @@ -231,12 +177,17 @@ namespace ClassicalSharp { for( ; y1 < endY; y1 += axisSize ) { y2 = y1 + axisSize; if( y2 > endY ) y2 = endY; - DrawZPlane( z, x1, x2, y1, y2, col, vertices ); + + TextureRectangle rec = new TextureRectangle( 0, 0, x2 - x1, y2 - y1 ); + *vertices++ = new VertexPos3fTex2fCol4b( x1, y1, z, rec.U1, rec.V1, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x1, y2, z, rec.U1, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y2, z, rec.U2, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y1, z, rec.U2, rec.V1, col ); } } } - void DrawYPlaneParts( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { + void DrawY( int x1, int z1, int x2, int z2, int y, int axisSize, FastColour col, ref VertexPos3fTex2fCol4b* vertices ) { int endX = x2, endZ = z2, startZ = z1; for( ; x1 < endX; x1 += axisSize ) { x2 = x1 + axisSize; @@ -245,12 +196,24 @@ namespace ClassicalSharp { for( ; z1 < endZ; z1 += axisSize ) { z2 = z1 + axisSize; if( z2 > endZ ) z2 = endZ; - DrawYPlane( x1, z1, x2, z2, y, col, vertices ); + + TextureRectangle rec = new TextureRectangle( 0, 0, x2 - x1, z2 - z1 ); + *vertices++ = new VertexPos3fTex2fCol4b( x1, y, z1, rec.U1, rec.V1, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x1, y, z2, rec.U1, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y, z2, rec.U2, rec.V2, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y, z1, rec.U2, rec.V1, col ); } } } - #endregion + Rectangle[] rects = new Rectangle[4]; + void CalculateRects( int extent ) { + rects[0] = new Rectangle( -extent, -extent, extent + Map.Width + extent, extent ); + rects[1] = new Rectangle( -extent, Map.Length, extent + Map.Width + extent, extent ); + + rects[2] = new Rectangle( -extent, 0, extent, Map.Length ); + rects[3] = new Rectangle( Map.Width, 0, extent, Map.Length ); + } int lastEdgeTexLoc, lastSideTexLoc; void MakeTexture( ref int texId, ref int lastTexLoc, Block block ) { @@ -261,38 +224,5 @@ namespace ClassicalSharp { texId = Window.TerrainAtlas.LoadTextureElement( texLoc ); } } - - void DrawXPlane( int x, int z1, int z2, int y1, int y2, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { - TextureRectangle rec = new TextureRectangle( 0, 0, z2 - z1, y2 - y1 ); - vertices[index++] = new VertexPos3fTex2fCol4b( x, y1, z1, rec.U1, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x, y2, z1, rec.U1, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x, y2, z2, rec.U2, rec.V2, col ); - - vertices[index++] = new VertexPos3fTex2fCol4b( x, y2, z2, rec.U2, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x, y1, z2, rec.U2, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x, y1, z1, rec.U1, rec.V1, col ); - } - - void DrawYPlane( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { - TextureRectangle rec = new TextureRectangle( 0, 0, x2 - x1, z2 - z1 ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z1, rec.U1, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z2, rec.U1, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z2, rec.U2, rec.V2, col ); - - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z2, rec.U2, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z1, rec.U2, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z1, rec.U1, rec.V1, col ); - } - - void DrawZPlane( int z, int x1, int x2, int y1, int y2, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { - TextureRectangle rec = new TextureRectangle( 0, 0, x2 - x1, y2 - y1 ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y1, z, rec.U1, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y2, z, rec.U1, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y2, z, rec.U2, rec.V2, col ); - - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y2, z, rec.U2, rec.V2, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y1, z, rec.U2, rec.V1, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y1, z, rec.U1, rec.V1, col ); - } } } \ No newline at end of file diff --git a/ClassicalSharp/Rendering/MapRenderer.cs b/ClassicalSharp/Rendering/MapRenderer.cs index 9aeae0127..2a81fc435 100644 --- a/ClassicalSharp/Rendering/MapRenderer.cs +++ b/ClassicalSharp/Rendering/MapRenderer.cs @@ -56,7 +56,6 @@ namespace ClassicalSharp { game.OnNewMapLoaded -= OnNewMapLoaded; game.EnvVariableChanged -= EnvVariableChanged; builder.Dispose(); - api.DeleteIb( chunkIb ); } public void Refresh() { @@ -188,14 +187,10 @@ namespace ClassicalSharp { public void Render( double deltaTime ) { if( chunks == null ) return; UpdateSortOrder(); - UpdateChunks(); - if( chunkIb == -1 ) - MakeIndices(); + UpdateChunks(); - api.BindIb( chunkIb ); RenderNormal(); game.MapEnvRenderer.Render( deltaTime ); - api.BindIb( chunkIb ); RenderTranslucent(); } @@ -274,25 +269,6 @@ namespace ClassicalSharp { api.Texturing = false; } - int chunkIb = -1; - unsafe void MakeIndices() { - int element = 0; - ushort* indices = stackalloc ushort[maxIndices]; - IntPtr ptr = (IntPtr)indices; - - for( int i = 0; i < maxIndices; i += 6 ) { - *indices++ = (ushort)( element + 0 ); - *indices++ = (ushort)( element + 1 ); - *indices++ = (ushort)( element + 2 ); - - *indices++ = (ushort)( element + 2 ); - *indices++ = (ushort)( element + 3 ); - *indices++ = (ushort)( element + 0 ); - element += 4; - } - chunkIb = api.CreateIb( ptr, maxIndices ); - } - // Render translucent(liquid) blocks. These 'blend' into other blocks. void RenderTranslucent() { // First fill depth buffer diff --git a/ClassicalSharp/Rendering/StandardEnvRenderer.cs b/ClassicalSharp/Rendering/StandardEnvRenderer.cs index 80ae7cba9..abb0f18aa 100644 --- a/ClassicalSharp/Rendering/StandardEnvRenderer.cs +++ b/ClassicalSharp/Rendering/StandardEnvRenderer.cs @@ -5,17 +5,16 @@ using OpenTK; namespace ClassicalSharp.Renderers { - public class StandardEnvRenderer : EnvRenderer { + public unsafe class StandardEnvRenderer : EnvRenderer { public StandardEnvRenderer( Game window ) { Window = window; Map = Window.Map; } - int cloudTexture = -1, cloudsVbo = -1, cloudsVertices; - int skyOffset = 10, skyVbo = -1, skyVertices; - int index; - public float CloudsSpeed = 1f; + int cloudTexture = -1, cloudsVb = -1, cloudsIndices; + int skyOffset = 10, skyVb = -1, skyIndices; + public float CloudsSpeed = 1; bool legacy; public void SetUseLegacyMode( bool legacy ) { @@ -25,12 +24,13 @@ namespace ClassicalSharp.Renderers { } public override void Render( double deltaTime ) { - if( skyVbo == -1 || cloudsVbo == -1 ) return; + if( skyVb == -1 || cloudsVb == -1 ) return; Vector3 pos = Window.LocalPlayer.EyePosition; if( pos.Y < Map.Height + skyOffset ) { Graphics.BeginVbBatch( VertexFormat.Pos3fCol4b ); - Graphics.DrawVb( DrawMode.Triangles, skyVbo, 0, skyVertices ); + Graphics.BindVb( skyVb ); + Graphics.DrawIndexedVb( DrawMode.Triangles, skyIndices, 0, 0 ); } RenderClouds( deltaTime ); ResetFog(); @@ -55,9 +55,9 @@ namespace ClassicalSharp.Renderers { public override void OnNewMap( object sender, EventArgs e ) { Graphics.Fog = false; - Graphics.DeleteVb( skyVbo ); - Graphics.DeleteVb( cloudsVbo ); - skyVbo = cloudsVbo = -1; + Graphics.DeleteVb( skyVb ); + Graphics.DeleteVb( cloudsVb ); + skyVb = cloudsVb = -1; } public override void OnNewMapLoaded( object sender, EventArgs e ) { @@ -82,8 +82,8 @@ namespace ClassicalSharp.Renderers { public override void Dispose() { base.Dispose(); Window.ViewDistanceChanged -= ResetAllEnv; - Graphics.DeleteVb( skyVbo ); - Graphics.DeleteVb( cloudsVbo ); + Graphics.DeleteVb( skyVb ); + Graphics.DeleteVb( cloudsVb ); Graphics.DeleteTexture( ref cloudTexture ); } @@ -99,7 +99,8 @@ namespace ClassicalSharp.Renderers { Graphics.Texturing = true; Graphics.BindTexture( cloudTexture ); Graphics.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); - Graphics.DrawVb( DrawMode.Triangles, cloudsVbo, 0, cloudsVertices ); + Graphics.BindVb( cloudsVb ); + Graphics.DrawIndexedVb( DrawMode.Triangles, cloudsIndices, 0, 0 ); Graphics.AlphaTest = false; Graphics.Texturing = false; @@ -147,114 +148,72 @@ namespace ClassicalSharp.Renderers { void ResetClouds() { if( Map.IsNotLoaded ) return; - index = 0; - Graphics.DeleteVb( cloudsVbo ); - int extent = Window.ViewDistance; - - if( legacy ) { - ResetCloudsLegacy( Map.Height + 2, -extent, -extent, Map.Width + extent, Map.Length + extent ); - } else { - ResetCloudsModern( Map.Height + 2, -extent, -extent, Map.Width + extent, Map.Length + extent ); - } + Graphics.DeleteVb( cloudsVb ); + ResetClouds( Window.ViewDistance, legacy ? 128 : 65536 ); } void ResetSky() { if( Map.IsNotLoaded ) return; - index = 0; - Graphics.DeleteVb( skyVbo ); - int extent = Window.ViewDistance; + Graphics.DeleteVb( skyVb ); + ResetSky( Window.ViewDistance, legacy ? 128 : 65536 ); + } + + void ResetClouds( int extent, int axisSize ) { + int x1 = -extent, x2 = Map.Width + extent; + int z1 = -extent, z2 = Map.Length + extent; + cloudsIndices = Utils.CountIndices( x2 - x1, z2 - z1, axisSize ); - if( legacy ) { - ResetSkyLegacy( Map.Height + skyOffset, -extent, -extent, Map.Width + extent, Map.Length + extent ); - } else { - ResetSkyModern( Map.Height + skyOffset, -extent, -extent, Map.Width + extent, Map.Length + extent ); - } + VertexPos3fTex2fCol4b* vertices = stackalloc VertexPos3fTex2fCol4b[cloudsIndices / 6 * 4]; + DrawCloudsY( x1, z1, x2, z2, Map.Height + 2, axisSize, Map.CloudsCol, vertices ); + cloudsVb = Graphics.CreateVb( (IntPtr)vertices, VertexFormat.Pos3fTex2fCol4b, cloudsIndices / 6 * 4 ); } - #region Modern - - void ResetCloudsModern( int y, int x1, int z1, int x2, int z2 ) { - cloudsVertices = 6; - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[cloudsVertices]; - DrawCloudsYPlane( x1, z1, x2, z2, y, Map.CloudsCol, vertices ); - cloudsVbo = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); + void ResetSky( int extent, int axisSize ) { + int x1 = -extent, x2 = Map.Width + extent; + int z1 = -extent, z2 = Map.Length + extent; + skyIndices = Utils.CountIndices( x2 - x1, z2 - z1, axisSize ); + + VertexPos3fCol4b* vertices = stackalloc VertexPos3fCol4b[skyIndices / 6 * 4]; + DrawSkyY( x1, z1, x2, z2, Map.Height + skyOffset, axisSize, Map.SkyCol, vertices ); + skyVb = Graphics.CreateVb( (IntPtr)vertices, VertexFormat.Pos3fCol4b, skyIndices / 6 * 4 ); } - void ResetSkyModern( int y, int x1, int z1, int x2, int z2 ) { - skyVertices = 6; - VertexPos3fCol4b[] vertices = new VertexPos3fCol4b[skyVertices]; - DrawSkyYPlane( x1, z1, x2, z2, y, Map.SkyCol, vertices ); - skyVbo = Graphics.CreateVb( vertices, VertexFormat.Pos3fCol4b ); - } - - #endregion - - #region Legacy - - void ResetCloudsLegacy( int y, int x1, int z1, int x2, int z2 ) { - cloudsVertices = Utils.CountVertices( x2 - x1, z2 - z1, 128 ); - VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[cloudsVertices]; - DrawCloudsYPlaneParts( x1, z1, x2, z2, y, Map.CloudsCol, vertices ); - cloudsVbo = Graphics.CreateVb( vertices, VertexFormat.Pos3fTex2fCol4b ); - } - - void ResetSkyLegacy( int y, int x1, int z1, int x2, int z2 ) { - skyVertices = Utils.CountVertices( x2 - x1, z2 - z1, 128 ); - VertexPos3fCol4b[] vertices = new VertexPos3fCol4b[skyVertices]; - DrawSkyYPlaneParts( x1, z1, x2, z2, y, Map.SkyCol, vertices ); - skyVbo = Graphics.CreateVb( vertices, VertexFormat.Pos3fCol4b ); - } - - void DrawSkyYPlaneParts( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fCol4b[] vertices ) { + void DrawSkyY( int x1, int z1, int x2, int z2, int y, int axisSize, FastColour col, VertexPos3fCol4b* vertices ) { int endX = x2, endZ = z2, startZ = z1; - for( ; x1 < endX; x1 += 128 ) { - x2 = x1 + 128; + for( ; x1 < endX; x1 += axisSize ) { + x2 = x1 + axisSize; if( x2 > endX ) x2 = endX; z1 = startZ; - for( ; z1 < endZ; z1 += 128 ) { - z2 = z1 + 128; + for( ; z1 < endZ; z1 += axisSize ) { + z2 = z1 + axisSize; if( z2 > endZ ) z2 = endZ; - DrawSkyYPlane( x1, z1, x2, z2, y, col, vertices ); + + *vertices++ = new VertexPos3fCol4b( x1, y, z1, col ); + *vertices++ = new VertexPos3fCol4b( x1, y, z2, col ); + *vertices++ = new VertexPos3fCol4b( x2, y, z2, col ); + *vertices++ = new VertexPos3fCol4b( x2, y, z1, col ); } } } - void DrawCloudsYPlaneParts( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { + void DrawCloudsY( int x1, int z1, int x2, int z2, int y, int axisSize, FastColour col, VertexPos3fTex2fCol4b* vertices ) { int endX = x2, endZ = z2, startZ = z1; - for( ; x1 < endX; x1 += 128 ) { - x2 = x1 + 128; + for( ; x1 < endX; x1 += axisSize ) { + x2 = x1 + axisSize; if( x2 > endX ) x2 = endX; z1 = startZ; - for( ; z1 < endZ; z1 += 128 ) { - z2 = z1 + 128; + for( ; z1 < endZ; z1 += axisSize ) { + z2 = z1 + axisSize; if( z2 > endZ ) z2 = endZ; - DrawCloudsYPlane( x1, z1, x2, z2, y, col, vertices ); + + *vertices++ = new VertexPos3fTex2fCol4b( x1, y, z1, x1 / 2048f, z1 / 2048f, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x1, y, z2, x1 / 2048f, z2 / 2048f, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y, z2, x2 / 2048f, z2 / 2048f, col ); + *vertices++ = new VertexPos3fTex2fCol4b( x2, y, z1, x2 / 2048f, z1 / 2048f, col ); } } } - - #endregion - - void DrawCloudsYPlane( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fTex2fCol4b[] vertices ) { - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z1, x1 / 2048f, z1 / 2048f, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z2, x1 / 2048f, z2 / 2048f, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z2, x2 / 2048f, z2 / 2048f, col ); - - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z2, x2 / 2048f, z2 / 2048f, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x2, y, z1, x2 / 2048f, z1 / 2048f, col ); - vertices[index++] = new VertexPos3fTex2fCol4b( x1, y, z1, x1 / 2048f, z1 / 2048f, col ); - } - - void DrawSkyYPlane( int x1, int z1, int x2, int z2, int y, FastColour col, VertexPos3fCol4b[] vertices ) { - vertices[index++] = new VertexPos3fCol4b( x1, y, z1, col ); - vertices[index++] = new VertexPos3fCol4b( x1, y, z2, col ); - vertices[index++] = new VertexPos3fCol4b( x2, y, z2, col ); - - vertices[index++] = new VertexPos3fCol4b( x2, y, z2, col ); - vertices[index++] = new VertexPos3fCol4b( x2, y, z1, col ); - vertices[index++] = new VertexPos3fCol4b( x1, y, z1, col ); - } } } \ No newline at end of file diff --git a/ClassicalSharp/Utils/Utils.cs b/ClassicalSharp/Utils/Utils.cs index 8502dece9..a542c9222 100644 --- a/ClassicalSharp/Utils/Utils.cs +++ b/ClassicalSharp/Utils/Utils.cs @@ -206,7 +206,7 @@ namespace ClassicalSharp { return a + ( b - a ) * t; } - internal static int CountVertices( int axis1Len, int axis2Len, int axisSize ) { + internal static int CountIndices( int axis1Len, int axis2Len, int axisSize ) { int cellsAxis1 = axis1Len / axisSize + ( axis1Len % axisSize != 0 ? 1 : 0 ); int cellsAxis2 = axis2Len / axisSize + ( axis2Len % axisSize != 0 ? 1 : 0 ); return cellsAxis1 * cellsAxis2 * 6;