Use dynamic VBOs instead of immediate mode.

This commit is contained in:
UnknownShadow200 2015-05-31 12:59:03 +10:00
parent ab42202a34
commit 0889c5f4df
8 changed files with 78 additions and 61 deletions

View File

@ -10,10 +10,12 @@ namespace ClassicalSharp.Particles {
List<Particle> particles = new List<Particle>();
public Game Window;
public IGraphicsApi Graphics;
int vb;
public ParticleManager( Game window ) {
Window = window;
Graphics = window.Graphics;
vb = Graphics.CreateDynamicVb( VertexFormat.VertexPos3fTex2f, 1000 );
}
VertexPos3fTex2f[] vertices = new VertexPos3fTex2f[0];
@ -32,7 +34,8 @@ namespace ClassicalSharp.Particles {
Graphics.Texturing = true;
Graphics.Bind2DTexture( Window.TerrainAtlas.TexId );
Graphics.AlphaTest = true;
Graphics.DrawVertices( DrawMode.Triangles, vertices, count );
count = Math.Min( count, 1000 );
Graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.VertexPos3fTex2f, count );
Graphics.AlphaTest = false;
Graphics.Texturing = false;
}
@ -48,6 +51,10 @@ namespace ClassicalSharp.Particles {
}
}
public void Dispose() {
Graphics.DeleteDynamicVb( vb );
}
int particleId = 0;
public void BreakBlockEffect( Vector3I position, byte block ) {
Vector3 startPos = new Vector3( position.X, position.Y, position.Z );

View File

@ -278,6 +278,8 @@ namespace ClassicalSharp {
TerrainAtlas.Dispose();
TerrainAtlas1D.Dispose();
ModelCache.Dispose();
Picking.Dispose();
ParticleManager.Dispose();
for( int i = 0; i < NetPlayers.Length; i++ ) {
if( NetPlayers[i] != null ) {
NetPlayers[i].Despawn();
@ -289,6 +291,7 @@ namespace ClassicalSharp {
if( writer != null ) {
writer.Close();
}
Graphics.Dispose();
Utils2D.Dispose();
base.Dispose();
}

View File

@ -98,14 +98,12 @@ namespace ClassicalSharp.GraphicsAPI {
/// <summary> Whether writing to the depth buffer is enabled. </summary>
public abstract bool DepthWrite { set; }
public abstract void DrawVertices( DrawMode mode, VertexPos3fCol4b[] vertices, int count );
public abstract void DrawVertices( DrawMode mode, VertexPos3fTex2f[] vertices, int count );
public abstract void DrawVertices( DrawMode mode, VertexPos3fTex2fCol4b[] vertices, int count );
public abstract void SetFillType( FillType type );
public abstract int CreateDynamicVb( VertexFormat format, int maxVertices );
public abstract void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, VertexFormat format, int count ) where T : struct;
public virtual int InitVb<T>( T[] vertices, VertexFormat format ) where T : struct {
return InitVb( vertices, format, vertices.Length );
}
@ -118,6 +116,8 @@ namespace ClassicalSharp.GraphicsAPI {
public abstract bool IsValidIb( int ib );
public abstract void DeleteDynamicVb( int id );
public abstract void DeleteVb( int id );
public abstract void DeleteIb( int ib );
@ -197,16 +197,28 @@ namespace ClassicalSharp.GraphicsAPI {
public abstract void OnWindowResize( int newWidth, int newHeight );
protected void InitDynamicBuffers() {
quadVb = CreateDynamicVb( VertexFormat.VertexPos3fCol4b, 4 );
texVb = CreateDynamicVb( VertexFormat.VertexPos3fTex2f, 4 );
}
public virtual void Dispose() {
DeleteDynamicVb( quadVb );
DeleteDynamicVb( texVb );
}
VertexPos3fCol4b[] quadVertices = new VertexPos3fCol4b[4];
int quadVb;
public virtual void Draw2DQuad( float x, float y, float width, float height, FastColour col ) {
quadVertices[0] = new VertexPos3fCol4b( x + width, y, 0, col );
quadVertices[1] = new VertexPos3fCol4b( x + width, y + height, 0, col );
quadVertices[2] = new VertexPos3fCol4b( x, y, 0, col );
quadVertices[3] = new VertexPos3fCol4b( x, y + height, 0, col );
DrawVertices( DrawMode.TriangleStrip, quadVertices, 4 );
DrawDynamicVb( DrawMode.TriangleStrip, quadVb, quadVertices, VertexFormat.VertexPos3fCol4b, 4 );
}
VertexPos3fTex2f[] texVertices = new VertexPos3fTex2f[4];
int texVb;
public virtual void Draw2DTexture( ref Texture tex ) {
float x1 = tex.X1, y1 = tex.Y1, x2 = tex.X2, y2 = tex.Y2;
// Have to order them this way because it's a triangle strip.
@ -214,7 +226,7 @@ namespace ClassicalSharp.GraphicsAPI {
texVertices[1] = new VertexPos3fTex2f( x2, y2, 0, tex.U2, tex.V2 );
texVertices[2] = new VertexPos3fTex2f( x1, y1, 0, tex.U1, tex.V1 );
texVertices[3] = new VertexPos3fTex2f( x1, y2, 0, tex.U1, tex.V2 );
DrawVertices( DrawMode.TriangleStrip, texVertices, 4 );
DrawDynamicVb( DrawMode.TriangleStrip, texVb, texVertices, VertexFormat.VertexPos3fTex2f, 4 );
}
public void Mode2D( float width, float height ) {

View File

@ -27,6 +27,7 @@ namespace ClassicalSharp.GraphicsAPI {
Utils.LogWarning( "Alternatively, you can download the 'DLCompatibility build." );
throw new InvalidOperationException( "Cannot use OpenGL vbos." );
}
base.InitDynamicBuffers();
drawBatchFuncCol4b = DrawVbPos3fCol4bFast;
drawBatchFuncTex2f = DrawVbPos3fTex2fFast;
drawBatchFuncTex2fCol4b = DrawVbPos3fTex2fCol4bFast;
@ -179,44 +180,6 @@ namespace ClassicalSharp.GraphicsAPI {
set { GL.DepthMask( value ); }
}
public override void DrawVertices( DrawMode mode, VertexPos3fCol4b[] vertices, int count ) {
//GL.DrawArrays( BeginMode.Triangles, 0, vertices.Length );
// We can't just use GL.DrawArrays since we'd have to pin the array to prevent it from being moved around in memory.
// Feasible alternatives:
// - Use a dynamically updated VBO, and resize it (i.e. create a new bigger VBO) if required.
// - Immediate mode.
GL.Begin( modeMappings[(int)mode] );
for( int i = 0; i < count; i++ ) {
VertexPos3fCol4b vertex = vertices[i];
GL.Color4( vertex.R, vertex.G, vertex.B, vertex.A );
GL.Vertex3( vertex.X, vertex.Y, vertex.Z );
}
GL.Color4( 1f, 1f, 1f, 1f );
GL.End();
}
public override void DrawVertices( DrawMode mode, VertexPos3fTex2f[] vertices, int count ) {
GL.Begin( modeMappings[(int)mode] );
for( int i = 0; i < count; i++ ) {
VertexPos3fTex2f vertex = vertices[i];
GL.TexCoord2( vertex.U, vertex.V );
GL.Vertex3( vertex.X, vertex.Y, vertex.Z );
}
GL.End();
}
public override void DrawVertices( DrawMode mode, VertexPos3fTex2fCol4b[] vertices, int count ) {
GL.Begin( modeMappings[(int)mode] );
for( int i = 0; i < count; i++ ) {
VertexPos3fTex2fCol4b vertex = vertices[i];
GL.TexCoord2( vertex.U, vertex.V );
GL.Color4( vertex.R, vertex.G, vertex.B, vertex.A );
GL.Vertex3( vertex.X, vertex.Y, vertex.Z );
}
GL.Color4( 1f, 1f, 1f, 1f );
GL.End();
}
PolygonMode[] fillModes = { PolygonMode.Point, PolygonMode.Line, PolygonMode.Fill };
public override void SetFillType( FillType type ) {
GL.PolygonMode( MaterialFace.FrontAndBack, fillModes[(int)type] );
@ -232,6 +195,17 @@ namespace ClassicalSharp.GraphicsAPI {
Action<DrawMode, int, int> drawBatchFuncCol4b;
Action<DrawMode, int, int> drawBatchFuncTex2fCol4b;
public override int CreateDynamicVb( VertexFormat format, int maxVertices ) {
int id = 0;
GL.Arb.GenBuffers( 1, out id );
int sizeInBytes = GetSizeInBytes( maxVertices, format );
GL.Arb.BindBuffer( BufferTargetArb.ArrayBuffer, id );
GL.Arb.BufferData( BufferTargetArb.ArrayBuffer, new IntPtr( sizeInBytes ), IntPtr.Zero, BufferUsageArb.DynamicDraw );
GL.Arb.BindBuffer( BufferTargetArb.ArrayBuffer, 0 );
return id;
}
public override int InitVb<T>( T[] vertices, VertexFormat format, int count ) {
int id = 0;
GL.Arb.GenBuffers( 1, out id );
@ -255,6 +229,21 @@ namespace ClassicalSharp.GraphicsAPI {
return id;
}
public override void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, VertexFormat format, int count ) {
int sizeInBytes = GetSizeInBytes( count, format );
GL.Arb.BindBuffer( BufferTargetArb.ArrayBuffer, vb );
GL.Arb.BufferSubData( BufferTargetArb.ArrayBuffer, IntPtr.Zero, new IntPtr( sizeInBytes ), vertices );
BeginVbBatch( format );
DrawVbBatch( mode, vb, count );
EndVbBatch();
}
public override void DeleteDynamicVb( int id ) {
if( id <= 0 ) return;
GL.Arb.DeleteBuffers( 1, ref id );
}
public override void DeleteVb( int id ) {
if( id <= 0 ) return;
#if TRACK_RESOURCES

View File

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
namespace Launcher {
@ -75,10 +74,6 @@ namespace Launcher {
{ "diams", '\x2666' },
};
static bool Lookup( string entity, out char decoded ) {
return _lookupTable.TryGetValue( entity, out decoded );
}
public static string HtmlDecode( string value ) {
value = value.Replace( "hellip;", "\x2026" ); // minecraft.net doesn't escape this at the end properly.
if( String.IsNullOrEmpty( value ) || value.IndexOf( '&' ) < 0 ) {
@ -119,7 +114,7 @@ namespace Launcher {
} else {
i = entityEnd;
char decodedEntity;
if( Lookup( entity, out decodedEntity ) ) {
if( _lookupTable.TryGetValue( entity, out decodedEntity ) ) {
output.Append( decodedEntity );
} else { // Invalid token.
output.Append( '&' );

View File

@ -9,8 +9,10 @@ namespace ClassicalSharp.Model {
public class BlockModel : IModel {
byte block = (byte)Block.Air;
int vb;
public BlockModel( Game window ) : base( window ) {
vertices = new VertexPos3fTex2fCol4b[6 * 6];
vb = window.Graphics.CreateDynamicVb( VertexFormat.VertexPos3fTex2fCol4b, 6 * 6 );
}
public override float NameYOffset {
@ -34,7 +36,7 @@ namespace ClassicalSharp.Model {
if( BlockInfo.IsSprite( block ) ) {
DrawXFace( 0f, TileSide.Right, false );
DrawZFace( 0f, TileSide.Back, false );
graphics.DrawVertices( DrawMode.Triangles, vertices, 6 * 2 );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.VertexPos3fTex2fCol4b, 6 * 2 );
} else {
DrawYFace( blockHeight, TileSide.Top );
DrawXFace( -0.5f, TileSide.Right, false );
@ -42,7 +44,7 @@ namespace ClassicalSharp.Model {
DrawZFace( -0.5f, TileSide.Front, true );
DrawZFace( 0.5f, TileSide.Back, false );
DrawYFace( 0f, TileSide.Bottom );
graphics.DrawVertices( DrawMode.Triangles, vertices, 6 * 6 );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.VertexPos3fTex2fCol4b, 6 * 6 );
}
}
float blockHeight;
@ -50,6 +52,7 @@ namespace ClassicalSharp.Model {
BlockInfo BlockInfo;
public override void Dispose() {
graphics.DeleteDynamicVb( vb );
}
void DrawYFace( float y, int side ) {

View File

@ -8,10 +8,12 @@ namespace ClassicalSharp.Renderers {
Game window;
IGraphicsApi graphics;
int vb;
public PickingRenderer( Game window ) {
this.window = window;
graphics = window.Graphics;
vb = graphics.CreateDynamicVb( VertexFormat.VertexPos3fCol4b, verticesCount );
}
FastColour col = FastColour.White;
@ -59,10 +61,14 @@ namespace ClassicalSharp.Renderers {
DrawZPlane( p2.Z, p2.X, p1.Y, p2.X - size, p2.Y );
DrawZPlane( p2.Z, p1.X, p1.Y, p2.X, p1.Y + size );
DrawZPlane( p2.Z, p1.X, p2.Y, p2.X, p2.Y - size );
graphics.DrawVertices( DrawMode.Triangles, vertices, verticesCount );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.VertexPos3fCol4b, verticesCount );
}
}
public void Dispose() {
graphics.DeleteDynamicVb( vb );
}
void DrawXPlane( float x, float z1, float y1, float z2, float y2 ) {
vertices[index++] = new VertexPos3fCol4b( x, y1, z1, col );
vertices[index++] = new VertexPos3fCol4b( x, y2, z1, col );

View File

@ -15,8 +15,10 @@ namespace ClassicalSharp {
map = Window.Map;
graphics = window.Graphics;
info = Window.BlockInfo;
weatherVb = graphics.CreateDynamicVb( VertexFormat.VertexPos3fTex2fCol4b, 12 * 9 * 9 );
}
int weatherVb;
int rainTexture, snowTexture;
short[] heightmap;
float vOffset;
@ -44,7 +46,7 @@ namespace ClassicalSharp {
MakeRainForSquare( pos.X + dx, rainY, height, pos.Z + dz, col, ref index );
}
}
graphics.DrawVertices( DrawMode.Triangles, vertices, index );
graphics.DrawDynamicVb( DrawMode.Triangles, weatherVb, vertices, VertexFormat.VertexPos3fTex2fCol4b, index );
graphics.AlphaBlending = false;
graphics.Texturing = false;
}