Use indexed drawing and stackalloc in StandardEnvRenderer.

This commit is contained in:
UnknownShadow200 2015-08-04 08:33:00 +10:00
parent 1590664f68
commit 0fe78fdf3b
7 changed files with 162 additions and 271 deletions

View File

@ -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();

View File

@ -128,6 +128,9 @@ namespace ClassicalSharp.GraphicsAPI {
public abstract void DrawIndexedVb( DrawMode mode, int indicesCount, int startVertex, int startIndex );
/// <summary> Optimised version of DrawIndexedVb for VertexFormat.Pos3fTex2fCol4b </summary>
//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 {

View File

@ -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 ) );

View File

@ -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<Rectangle> 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 );
}
}
}

View File

@ -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

View File

@ -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 );
}
}
}

View File

@ -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;