Add support for drawing indexed dynamic VBs - use less memory in WeatherRenderer and can draw more particles in ParticleManager.

This commit is contained in:
UnknownShadow200 2015-09-03 06:32:28 +10:00
parent 9394ce1794
commit 4371246f96
9 changed files with 70 additions and 73 deletions

View File

@ -35,7 +35,9 @@ namespace ClassicalSharp.Particles {
graphics.BindTexture( game.TerrainAtlas.TexId );
graphics.AlphaTest = true;
count = Math.Min( count, 1000 );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.Pos3fTex2f, count );
graphics.BeginVbBatch( VertexFormat.Pos3fTex2f );
graphics.DrawDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
graphics.AlphaTest = false;
graphics.Texturing = false;
}

View File

@ -20,11 +20,8 @@ namespace ClassicalSharp.Particles {
vertices[index++] = new VertexPos3fTex2f( p111, Rectangle.U1, Rectangle.V2 );
vertices[index++] = new VertexPos3fTex2f( p121, Rectangle.U1, Rectangle.V1 );
vertices[index++] = new VertexPos3fTex2f( p222, Rectangle.U2, Rectangle.V1 );
vertices[index++] = new VertexPos3fTex2f( p222, Rectangle.U2, Rectangle.V1 );
vertices[index++] = new VertexPos3fTex2f( p212, Rectangle.U2, Rectangle.V2 );
vertices[index++] = new VertexPos3fTex2f( p111, Rectangle.U1, Rectangle.V2 );
}
public override bool Tick( double delta ) {

View File

@ -45,11 +45,13 @@ namespace ClassicalSharp {
pos.Y += Model.NameYOffset;
// Inlined translation + rotation Y axis
api.texVerts[0] = new VertexPos3fTex2f( cosA * x2 + pos.X, y1 + pos.Y, sinA * x2 + pos.Z, nameTex.U2, nameTex.V1 );
api.texVerts[1] = new VertexPos3fTex2f( cosA * x2 + pos.X, y2 + pos.Y, sinA * x2 + pos.Z, nameTex.U2, nameTex.V2 );
api.texVerts[2] = new VertexPos3fTex2f( cosA * x1 + pos.X, y1 + pos.Y, sinA * x1 + pos.Z, nameTex.U1, nameTex.V1 );
api.texVerts[0] = new VertexPos3fTex2f( cosA * x1 + pos.X, y1 + pos.Y, sinA * x1 + pos.Z, nameTex.U1, nameTex.V1 );
api.texVerts[1] = new VertexPos3fTex2f( cosA * x2 + pos.X, y1 + pos.Y, sinA * x2 + pos.Z, nameTex.U2, nameTex.V1 );
api.texVerts[2] = new VertexPos3fTex2f( cosA * x2 + pos.X, y2 + pos.Y, sinA * x2 + pos.Z, nameTex.U2, nameTex.V2 );
api.texVerts[3] = new VertexPos3fTex2f( cosA * x1 + pos.X, y2 + pos.Y, sinA * x1 + pos.Z, nameTex.U1, nameTex.V2 );
api.DrawDynamicVb( DrawMode.TriangleStrip, api.texVb, api.texVerts, VertexFormat.Pos3fTex2f, 4 );
api.BeginVbBatch( VertexFormat.Pos3fTex2f );
api.DrawDynamicIndexedVb( DrawMode.Triangles, api.texVb, api.texVerts, 4, 6 );
api.Texturing = false;
api.AlphaTest = false;
}

View File

@ -219,17 +219,24 @@ namespace ClassicalSharp.GraphicsAPI {
return GetOrExpand( ref dynamicvBuffers, buffer, iBufferSize );
}
public override void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, VertexFormat format, int count ) {
int size = count * strideSizes[(int)format];
public override void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, int count ) {
int size = count * batchStride;
DataBuffer buffer = dynamicvBuffers[vb];
buffer.SetData( vertices, size, LockFlags.Discard );
device.SetVertexFormat( formatMapping[(int)format] );
batchStride = strideSizes[(int)format];
device.SetStreamSource( 0, buffer, 0, batchStride );
device.DrawPrimitives( modeMappings[(int)mode], 0, NumPrimitives( count, mode ) );
}
public override void DrawDynamicIndexedVb<T>( DrawMode mode, int vb, T[] vertices, int vCount, int indicesCount ) {
int size = vCount * batchStride;
DataBuffer buffer = dynamicvBuffers[vb];
buffer.SetData( vertices, size, LockFlags.Discard );
device.SetStreamSource( 0, buffer, 0, batchStride );
device.DrawIndexedPrimitives( modeMappings[(int)mode], 0, 0, indicesCount / 6 * 4, 0, NumPrimitives( indicesCount, mode ) );
}
public override void DeleteDynamicVb( int id ) {
Delete( dynamicvBuffers, id );
}
@ -518,12 +525,7 @@ namespace ClassicalSharp.GraphicsAPI {
}
static int NumPrimitives( int vertices, DrawMode mode ) {
if( mode == DrawMode.Triangles ) {
return vertices / 3;
} else if( mode == DrawMode.TriangleStrip ) {
return vertices - 2;
}
return vertices / 2;
return mode == DrawMode.Triangles ? vertices / 3 : vertices / 2;
}
protected unsafe override void LoadOrthoMatrix( float width, float height ) {

View File

@ -123,7 +123,9 @@ namespace ClassicalSharp.GraphicsAPI {
public abstract void DeleteIb( int ib );
public abstract void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, VertexFormat format, int count ) where T : struct;
public abstract void DrawDynamicVb<T>( DrawMode mode, int vb, T[] vertices, int count ) where T : struct;
public abstract void DrawDynamicIndexedVb<T>( DrawMode mode, int vb, T[] vertices, int vCount, int indicesCount ) where T : struct;
public abstract void BeginVbBatch( VertexFormat format );
@ -173,14 +175,15 @@ namespace ClassicalSharp.GraphicsAPI {
DeleteDynamicVb( texVb );
}
VertexPos3fCol4b[] quadVertices = new VertexPos3fCol4b[4];
VertexPos3fCol4b[] quadVerts = 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 );
DrawDynamicVb( DrawMode.TriangleStrip, quadVb, quadVertices, VertexFormat.Pos3fCol4b, 4 );
quadVerts[0] = new VertexPos3fCol4b( x, y, 0, col );
quadVerts[1] = new VertexPos3fCol4b( x + width, y, 0, col );
quadVerts[2] = new VertexPos3fCol4b( x + width, y + height, 0, col );
quadVerts[3] = new VertexPos3fCol4b( x, y + height, 0, col );
BeginVbBatch( VertexFormat.Pos3fCol4b );
DrawDynamicIndexedVb( DrawMode.Triangles, quadVb, quadVerts, 4, 6 );
}
internal VertexPos3fTex2f[] texVerts = new VertexPos3fTex2f[4];
@ -195,12 +198,12 @@ namespace ClassicalSharp.GraphicsAPI {
y1 -= 0.5f;
y2 -= 0.5f;
#endif
// Have to order them this way because it's a triangle strip.
texVerts[0] = new VertexPos3fTex2f( x2, y1, 0, tex.U2, tex.V1 );
texVerts[1] = new VertexPos3fTex2f( x2, y2, 0, tex.U2, tex.V2 );
texVerts[2] = new VertexPos3fTex2f( x1, y1, 0, tex.U1, tex.V1 );
texVerts[0] = new VertexPos3fTex2f( x1, y1, 0, tex.U1, tex.V1 );
texVerts[1] = new VertexPos3fTex2f( x2, y1, 0, tex.U2, tex.V1 );
texVerts[2] = new VertexPos3fTex2f( x2, y2, 0, tex.U2, tex.V2 );
texVerts[3] = new VertexPos3fTex2f( x1, y2, 0, tex.U1, tex.V2 );
DrawDynamicVb( DrawMode.TriangleStrip, texVb, texVerts, VertexFormat.Pos3fTex2f, 4 );
BeginVbBatch( VertexFormat.Pos3fTex2f );
DrawDynamicIndexedVb( DrawMode.Triangles, texVb, texVerts, 4, 6 );
}
public void Mode2D( float width, float height ) {
@ -259,7 +262,6 @@ namespace ClassicalSharp.GraphicsAPI {
public enum DrawMode {
Triangles = 0,
Lines = 1,
TriangleStrip = 2,
}
public enum CompareFunc {

View File

@ -224,16 +224,25 @@ namespace ClassicalSharp.GraphicsAPI {
return id;
}
public override void DrawDynamicVb<T>( DrawMode mode, int id, T[] vertices, VertexFormat format, int count ) {
int sizeInBytes = count * strideSizes[(int)format];
int batchStride;
public override void DrawDynamicVb<T>( DrawMode mode, int id, T[] vertices, int count ) {
int sizeInBytes = count * batchStride;
GL.BindBufferARB( BufferTarget.ArrayBuffer, id );
GL.BufferSubDataARB( BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr( sizeInBytes ), vertices );
BeginVbBatch( format );
setupBatchFunc();
GL.DrawArrays( modeMappings[(int)mode], 0, count );
}
public override void DrawDynamicIndexedVb<T>( DrawMode mode, int id, T[] vertices, int vCount, int indicesCount ) {
int sizeInBytes = vCount * batchStride;
GL.BindBufferARB( BufferTarget.ArrayBuffer, id );
GL.BufferSubDataARB( BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr( sizeInBytes ), vertices );
setupBatchFunc();
GL.DrawElements( modeMappings[(int)mode], indicesCount, indexType, zero );
}
public unsafe override void DeleteDynamicVb( int id ) {
if( id <= 0 ) return;
GL.DeleteBuffersARB( 1, &id );
@ -267,12 +276,15 @@ namespace ClassicalSharp.GraphicsAPI {
GL.EnableClientState( ArrayCap.ColorArray );
GL.EnableClientState( ArrayCap.TextureCoordArray );
setupBatchFunc = setupBatchFuncTex2fCol4b;
batchStride = VertexPos3fTex2fCol4b.Size;
} else if( format == VertexFormat.Pos3fTex2f ) {
GL.EnableClientState( ArrayCap.TextureCoordArray );
setupBatchFunc = setupBatchFuncTex2f;
batchStride = VertexPos3fTex2f.Size;
} else if( format == VertexFormat.Pos3fCol4b ) {
GL.EnableClientState( ArrayCap.ColorArray );
setupBatchFunc = setupBatchFuncCol4b;
batchStride = VertexPos3fCol4b.Size;
}
}

View File

@ -8,9 +8,9 @@ namespace ClassicalSharp.Model {
public class BlockModel : IModel {
byte block = (byte)Block.Air;
public BlockModel( Game window ) : base( window ) {
public BlockModel( Game game ) : base( game ) {
vertices = new VertexPos3fTex2fCol4b[6 * 6];
vb = window.Graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, 6 * 6 );
vb = game.Graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, vertices.Length );
}
public override float NameYOffset {
@ -40,10 +40,12 @@ namespace ClassicalSharp.Model {
atlas = window.TerrainAtlas;
BlockInfo = window.BlockInfo;
index = 0;
graphics.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b );
if( BlockInfo.IsSprite( block ) ) {
DrawXFace( 0f, TileSide.Right, false );
DrawZFace( 0f, TileSide.Back, false );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.Pos3fTex2fCol4b, 6 * 2 );
graphics.DrawDynamicIndexedVb( DrawMode.Triangles, vb, vertices, 2 * 4, 2 * 6 );
} else {
DrawYFace( blockHeight, TileSide.Top );
DrawXFace( -0.5f, TileSide.Right, false );
@ -51,7 +53,7 @@ namespace ClassicalSharp.Model {
DrawZFace( -0.5f, TileSide.Front, true );
DrawZFace( 0.5f, TileSide.Back, false );
DrawYFace( 0f, TileSide.Bottom );
graphics.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.Pos3fTex2fCol4b, 6 * 6 );
graphics.DrawDynamicIndexedVb( DrawMode.Triangles, vb, vertices, 6 * 4, 6 * 6 );
}
}
float blockHeight;
@ -67,12 +69,9 @@ namespace ClassicalSharp.Model {
TextureRectangle rec = atlas.GetTexRec( texId );
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, y, -0.5f, rec.U1, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, y, -0.5f, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, y, 0.5f, rec.U2, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, y, -0.5f, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, y, 0.5f, rec.U2, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, y, 0.5f, rec.U1, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, y, -0.5f, rec.U1, rec.V1, col );
}
void DrawZFace( float z, int side, bool swapU ) {
@ -85,11 +84,8 @@ namespace ClassicalSharp.Model {
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, 0f, z, rec.U1, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, blockHeight, z, rec.U1, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, blockHeight, z, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, blockHeight, z, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( 0.5f, 0f, z, rec.U2, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( -0.5f, 0f, z, rec.U1, rec.V2, col );
}
void DrawXFace( float x, int side, bool swapU ) {
@ -102,11 +98,8 @@ namespace ClassicalSharp.Model {
vertices[index++] = new VertexPos3fTex2fCol4b( x, 0f, -0.5f, rec.U1, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, blockHeight, -0.5f, rec.U1, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, blockHeight, 0.5f, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, blockHeight, 0.5f, rec.U2, rec.V1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, 0f, 0.5f, rec.U2, rec.V2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, 0f, -0.5f, rec.U1, rec.V2, col );
}
}
}

View File

@ -16,7 +16,7 @@ namespace ClassicalSharp.Renderers {
FastColour col = FastColour.White;
int index;
const int verticesCount = 24 * ( 3 * 2 );
const int verticesCount = 16 * 6;
VertexPos3fCol4b[] vertices = new VertexPos3fCol4b[verticesCount];
const float size = 0.0625f;
const float offset = 0.01f;
@ -56,7 +56,9 @@ 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.DrawDynamicVb( DrawMode.Triangles, vb, vertices, VertexFormat.Pos3fCol4b, verticesCount );
graphics.BeginVbBatch( VertexFormat.Pos3fCol4b );
graphics.DrawDynamicIndexedVb( DrawMode.Triangles, vb, vertices, verticesCount, verticesCount * 6 / 4 );
}
public void Dispose() {
@ -65,32 +67,23 @@ namespace ClassicalSharp.Renderers {
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 );
vertices[index++] = new VertexPos3fCol4b( x, y2, z2, col );
vertices[index++] = new VertexPos3fCol4b( x, y2, z1, col );
vertices[index++] = new VertexPos3fCol4b( x, y2, z2, col );
vertices[index++] = new VertexPos3fCol4b( x, y1, z2, col );
vertices[index++] = new VertexPos3fCol4b( x, y1, z1, col );
}
void DrawZPlane( float z, float x1, float y1, float x2, float y2 ) {
vertices[index++] = new VertexPos3fCol4b( x1, y1, z, col );
vertices[index++] = new VertexPos3fCol4b( x1, y2, z, col );
vertices[index++] = new VertexPos3fCol4b( x2, y2, z, col );
vertices[index++] = new VertexPos3fCol4b( x1, y2, z, col );
vertices[index++] = new VertexPos3fCol4b( x2, y2, z, col );
vertices[index++] = new VertexPos3fCol4b( x2, y1, z, col );
vertices[index++] = new VertexPos3fCol4b( x1, y1, z, col );
}
void DrawYPlane( float y, float x1, float z1, float x2, float z2 ) {
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 );
}
}
}

View File

@ -22,7 +22,7 @@ namespace ClassicalSharp {
int rainTexture, snowTexture;
short[] heightmap;
float vOffset;
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[12 * 9 * 9];
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[8 * 9 * 9];
public void Render( double deltaTime ) {
Weather weather = map.Weather;
if( weather == Weather.Sunny ) return;
@ -46,7 +46,8 @@ namespace ClassicalSharp {
MakeRainForSquare( pos.X + dx, rainY, height, pos.Z + dz, col, ref index );
}
}
graphics.DrawDynamicVb( DrawMode.Triangles, weatherVb, vertices, VertexFormat.Pos3fTex2fCol4b, index );
graphics.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b );
graphics.DrawDynamicIndexedVb( DrawMode.Triangles, weatherVb, vertices, index, index * 6 / 4 );
graphics.AlphaBlending = false;
graphics.Texturing = false;
}
@ -61,21 +62,14 @@ namespace ClassicalSharp {
float v2 = height / 6f + v1;
vertices[index++] = new VertexPos3fTex2fCol4b( x, y, z, 0, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y + height, z, 0, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y + height, z, 0, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y + height, z + 1, 2, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y + height, z + 1, 2, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z + 1, 2, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y, z, 0, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z + 1, 2, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z, 2, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y + height, z, 2, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y + height, z + 1, 0, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y + height, z, 2, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y + height, z + 1, 0, v1, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x, y, z + 1, 0, v2, col );
vertices[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z, 2, v2, col );
}
int length, width, maxY, oneY;