Use a single VB per chunk, instead of one per 1D atlas, and another one per 1D atlas for translucent

This commit is contained in:
UnknownShadow200 2018-05-31 15:40:02 +10:00
parent 8ed8d02cc1
commit 7a7c5f1586
10 changed files with 326 additions and 284 deletions

View File

@ -151,15 +151,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Left]; int index = part.vIndex[Side.Left];
if (aY0_Z0 + aY1_Z1 > aY0_Z1 + aY1_Z0) { if (aY0_Z0 + aY1_Z1 > aY0_Z1 + aY1_Z0) {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col1_0); vertices[index ] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col1_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z2 + (count - 1), u2, v2, col0_1); vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z2 + (count - 1), u2, v2, col0_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x1, y2, z2 + (count - 1), u2, v1, col1_1); vertices[index + 3] = new VertexP3fT2fC4b(x1, y2, z2 + (count - 1), u2, v1, col1_1);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y2, z2 + (count - 1), u2, v1, col1_1); vertices[index ] = new VertexP3fT2fC4b(x1, y2, z2 + (count - 1), u2, v1, col1_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col1_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col1_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0); vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x1, y1, z2 + (count - 1), u2, v2, col0_1); vertices[index + 3] = new VertexP3fT2fC4b(x1, y1, z2 + (count - 1), u2, v2, col0_1);
} }
part.vIndex[Side.Left] += 4; part.vIndex[Side.Left] += 4;
} }
@ -193,15 +193,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Right]; int index = part.vIndex[Side.Right];
if (aY0_Z0 + aY1_Z1 > aY0_Z1 + aY1_Z0) { if (aY0_Z0 + aY1_Z1 > aY0_Z1 + aY1_Z0) {
part.vertices[index ] = new VertexP3fT2fC4b(x2, y2, z1, u1, v1, col1_0); vertices[index ] = new VertexP3fT2fC4b(x2, y2, z1, u1, v1, col1_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x2, y2, z2 + (count - 1), u2, v1, col1_1); vertices[index + 1] = new VertexP3fT2fC4b(x2, y2, z2 + (count - 1), u2, v1, col1_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2, y1, z2 + (count - 1), u2, v2, col0_1); vertices[index + 2] = new VertexP3fT2fC4b(x2, y1, z2 + (count - 1), u2, v2, col0_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2, y1, z1, u1, v2, col0_0); vertices[index + 3] = new VertexP3fT2fC4b(x2, y1, z1, u1, v2, col0_0);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x2, y2, z2 + (count - 1), u2, v1, col1_1); vertices[index ] = new VertexP3fT2fC4b(x2, y2, z2 + (count - 1), u2, v1, col1_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x2, y1, z2 + (count - 1), u2, v2, col0_1); vertices[index + 1] = new VertexP3fT2fC4b(x2, y1, z2 + (count - 1), u2, v2, col0_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2, y1, z1, u1, v2, col0_0); vertices[index + 2] = new VertexP3fT2fC4b(x2, y1, z1, u1, v2, col0_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2, y2, z1, u1, v1, col1_0); vertices[index + 3] = new VertexP3fT2fC4b(x2, y2, z1, u1, v1, col1_0);
} }
part.vIndex[Side.Right] += 4; part.vIndex[Side.Right] += 4;
} }
@ -235,15 +235,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Front]; int index = part.vIndex[Side.Front];
if (aX1_Y1 + aX0_Y0 > aX0_Y1 + aX1_Y0) { if (aX1_Y1 + aX0_Y0 > aX0_Y1 + aX1_Y0) {
part.vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v2, col1_0); vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v2, col1_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_1); vertices[index + 2] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_1); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_1);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0); vertices[index ] = new VertexP3fT2fC4b(x1, y1, z1, u1, v2, col0_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_1); vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_1); vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v2, col1_0); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v2, col1_0);
} }
part.vIndex[Side.Front] += 4; part.vIndex[Side.Front] += 4;
} }
@ -277,15 +277,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Back]; int index = part.vIndex[Side.Back];
if (aX1_Y1 + aX0_Y0 > aX0_Y1 + aX1_Y0) { if (aX1_Y1 + aX0_Y0 > aX0_Y1 + aX1_Y0) {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y2, z2, u1, v1, col0_1); vertices[index ] = new VertexP3fT2fC4b(x1, y2, z2, u1, v1, col0_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_0); vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v1, col1_1); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v1, col1_1);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v1, col1_1); vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v1, col1_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z2, u1, v1, col0_1); vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z2, u1, v1, col0_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_0); vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_0); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_0);
} }
part.vIndex[Side.Back] += 4; part.vIndex[Side.Back] += 4;
} }
@ -319,15 +319,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Bottom]; int index = part.vIndex[Side.Bottom];
if (aX0_Z1 + aX1_Z0 > aX0_Z0 + aX1_Z1) { if (aX0_Z1 + aX1_Z0 > aX0_Z0 + aX1_Z1) {
part.vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_1); vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_1); vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z1, u1, v1, col0_0); vertices[index + 2] = new VertexP3fT2fC4b(x1, y1, z1, u1, v1, col0_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v1, col1_0); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v1, col1_0);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_1); vertices[index ] = new VertexP3fT2fC4b(x1, y1, z2, u1, v2, col0_1);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v1, col0_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y1, z1, u1, v1, col0_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v1, col1_0); vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z1, u2, v1, col1_0);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_1); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y1, z2, u2, v2, col1_1);
} }
part.vIndex[Side.Bottom] += 4; part.vIndex[Side.Bottom] += 4;
} }
@ -361,15 +361,15 @@ namespace ClassicalSharp {
int index = part.vIndex[Side.Top]; int index = part.vIndex[Side.Top];
if (aX0_Z0 + aX1_Z1 > aX0_Z1 + aX1_Z0) { if (aX0_Z0 + aX1_Z1 > aX0_Z1 + aX1_Z0) {
part.vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_0); vertices[index ] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_0); vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_0);
part.vertices[index + 2] = new VertexP3fT2fC4b(x1, y2, z2, u1, v2, col0_1); vertices[index + 2] = new VertexP3fT2fC4b(x1, y2, z2, u1, v2, col0_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v2, col1_1); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v2, col1_1);
} else { } else {
part.vertices[index ] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_0); vertices[index ] = new VertexP3fT2fC4b(x1, y2, z1, u1, v1, col0_0);
part.vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z2, u1, v2, col0_1); vertices[index + 1] = new VertexP3fT2fC4b(x1, y2, z2, u1, v2, col0_1);
part.vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v2, col1_1); vertices[index + 2] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z2, u2, v2, col1_1);
part.vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_0); vertices[index + 3] = new VertexP3fT2fC4b(x2 + (count - 1), y2, z1, u2, v1, col1_0);
} }
part.vIndex[Side.Top] += 4; part.vIndex[Side.Top] += 4;
} }

View File

@ -36,6 +36,7 @@ namespace ClassicalSharp {
protected byte* counts; protected byte* counts;
protected int* bitFlags; protected int* bitFlags;
protected bool useBitFlags; protected bool useBitFlags;
protected VertexP3fT2fC4b[] vertices;
bool BuildChunk(int x1, int y1, int z1, ref bool allAir) { bool BuildChunk(int x1, int y1, int z1, ref bool allAir) {
light = game.Lighting; light = game.Lighting;
@ -162,9 +163,17 @@ namespace ClassicalSharp {
int x = info.CentreX - 8, y = info.CentreY - 8, z = info.CentreZ - 8; int x = info.CentreX - 8, y = info.CentreY - 8, z = info.CentreZ - 8;
if (!BuildChunk(x, y, z, ref info.AllAir)) return; if (!BuildChunk(x, y, z, ref info.AllAir)) return;
int totalVerts = TotalVerticesCount();
if (totalVerts == 0) return;
fixed (VertexP3fT2fC4b* ptr = vertices) {
// add an extra element to fix crashing on some GPUs
info.VbId = game.Graphics.CreateVb((IntPtr)ptr, VertexFormat.P3fT2fC4b, totalVerts + 1);
}
int offset = 0;
for (int i = 0; i < arraysCount; i++) { for (int i = 0; i < arraysCount; i++) {
SetPartInfo(normalParts[i], i, ref info.NormalParts); SetPartInfo(normalParts[i], ref offset, i, ref info.NormalParts);
SetPartInfo(translucentParts[i], i, ref info.TranslucentParts); SetPartInfo(translucentParts[i], ref offset, i, ref info.TranslucentParts);
} }
#if OCCLUSION #if OCCLUSION
@ -173,16 +182,13 @@ namespace ClassicalSharp {
#endif #endif
} }
void SetPartInfo(DrawInfo part, int i, ref ChunkPartInfo[] parts) { void SetPartInfo(DrawInfo part, ref int offset, int i, ref ChunkPartInfo[] parts) {
int vertCount = part.VerticesCount(); int vertCount = part.VerticesCount();
if (vertCount == 0) return; if (vertCount == 0) return;
ChunkPartInfo info; ChunkPartInfo info;
fixed (VertexP3fT2fC4b* ptr = part.vertices) { info.Offset = offset;
// add an extra element to fix crashing on some GPUs offset += vertCount;
info.VbId = game.Graphics.CreateVb((IntPtr)ptr, VertexFormat.P3fT2fC4b, vertCount + 1);
}
info.VerticesCount = vertCount;
info.LeftCount = (ushort)part.vCount[Side.Left]; info.LeftCount = (ushort)part.vCount[Side.Left];
info.RightCount = (ushort)part.vCount[Side.Right]; info.RightCount = (ushort)part.vCount[Side.Right];
@ -193,8 +199,10 @@ namespace ClassicalSharp {
info.SpriteCount = part.spriteCount; info.SpriteCount = part.spriteCount;
// Lazy initalize part arrays so we can save time in MapRenderer for chunks that only contain 1 or 2 part types. // Lazy initalize part arrays so we can save time in MapRenderer for chunks that only contain 1 or 2 part types.
if (parts == null) if (parts == null) {
parts = new ChunkPartInfo[arraysCount]; parts = new ChunkPartInfo[arraysCount];
for (int j = 0; j < parts.Length; j++) { parts[j].Offset = -1; }
}
parts[i] = info; parts[i] = info;
} }

View File

@ -132,7 +132,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : int col = fullBright ? FastColour.WhitePacked :
X >= offset ? light.LightCol_XSide_Fast(X - offset, Y, Z) : light.OutsideXSide; X >= offset ? light.LightCol_XSide_Fast(X - offset, Y, Z) : light.OutsideXSide;
drawer.Left(leftCount, col, texLoc, part.vertices, ref part.vIndex[Side.Left]); drawer.Left(leftCount, col, texLoc, vertices, ref part.vIndex[Side.Left]);
} }
if (rightCount != 0) { if (rightCount != 0) {
@ -143,7 +143,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : int col = fullBright ? FastColour.WhitePacked :
X <= (maxX - offset) ? light.LightCol_XSide_Fast(X + offset, Y, Z) : light.OutsideXSide; X <= (maxX - offset) ? light.LightCol_XSide_Fast(X + offset, Y, Z) : light.OutsideXSide;
drawer.Right(rightCount, col, texLoc, part.vertices, ref part.vIndex[Side.Right]); drawer.Right(rightCount, col, texLoc, vertices, ref part.vIndex[Side.Right]);
} }
if (frontCount != 0) { if (frontCount != 0) {
@ -154,7 +154,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : int col = fullBright ? FastColour.WhitePacked :
Z >= offset ? light.LightCol_ZSide_Fast(X, Y, Z - offset) : light.OutsideZSide; Z >= offset ? light.LightCol_ZSide_Fast(X, Y, Z - offset) : light.OutsideZSide;
drawer.Front(frontCount, col, texLoc, part.vertices, ref part.vIndex[Side.Front]); drawer.Front(frontCount, col, texLoc, vertices, ref part.vIndex[Side.Front]);
} }
if (backCount != 0) { if (backCount != 0) {
@ -165,7 +165,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : int col = fullBright ? FastColour.WhitePacked :
Z <= (maxZ - offset) ? light.LightCol_ZSide_Fast(X, Y, Z + offset) : light.OutsideZSide; Z <= (maxZ - offset) ? light.LightCol_ZSide_Fast(X, Y, Z + offset) : light.OutsideZSide;
drawer.Back(backCount, col, texLoc, part.vertices, ref part.vIndex[Side.Back]); drawer.Back(backCount, col, texLoc, vertices, ref part.vIndex[Side.Back]);
} }
if (bottomCount != 0) { if (bottomCount != 0) {
@ -175,7 +175,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : light.LightCol_YBottom_Fast(X, Y - offset, Z); int col = fullBright ? FastColour.WhitePacked : light.LightCol_YBottom_Fast(X, Y - offset, Z);
drawer.Bottom(bottomCount, col, texLoc, part.vertices, ref part.vIndex[Side.Bottom]); drawer.Bottom(bottomCount, col, texLoc, vertices, ref part.vIndex[Side.Bottom]);
} }
if (topCount != 0) { if (topCount != 0) {
@ -185,7 +185,7 @@ namespace ClassicalSharp {
DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i]; DrawInfo part = isTranslucent ? translucentParts[i] : normalParts[i];
int col = fullBright ? FastColour.WhitePacked : light.LightCol_YTop_Fast(X, (Y + 1) - offset, Z); int col = fullBright ? FastColour.WhitePacked : light.LightCol_YTop_Fast(X, (Y + 1) - offset, Z);
drawer.Top(topCount, col, texLoc, part.vertices, ref part.vIndex[Side.Top]); drawer.Top(topCount, col, texLoc, vertices, ref part.vIndex[Side.Top]);
} }
} }
} }

View File

@ -35,7 +35,6 @@ namespace ClassicalSharp {
} }
protected class DrawInfo { protected class DrawInfo {
public VertexP3fT2fC4b[] vertices;
public int[] vIndex = new int[6], vCount = new int[6]; public int[] vIndex = new int[6], vCount = new int[6];
public int spriteCount, sIndex, sAdvance; public int spriteCount, sIndex, sAdvance;
@ -45,21 +44,18 @@ namespace ClassicalSharp {
return count; return count;
} }
public void ExpandToCapacity() { public void CalcOffsets(ref int offset) {
int vertsCount = VerticesCount(); sIndex = offset;
if (vertices == null || (vertsCount + 2) > vertices.Length) {
vertices = new VertexP3fT2fC4b[vertsCount + 2];
// ensure buffer is up to 64 bits aligned for last element
}
sIndex = 0;
sAdvance = spriteCount / 4; sAdvance = spriteCount / 4;
vIndex[Side.Left] = spriteCount; vIndex[Side.Left] = spriteCount + offset;
vIndex[Side.Right] = vIndex[Side.Left] + vCount[Side.Left]; vIndex[Side.Right] = vIndex[Side.Left] + vCount[Side.Left];
vIndex[Side.Front] = vIndex[Side.Right] + vCount[Side.Right]; vIndex[Side.Front] = vIndex[Side.Right] + vCount[Side.Right];
vIndex[Side.Back] = vIndex[Side.Front] + vCount[Side.Front]; vIndex[Side.Back] = vIndex[Side.Front] + vCount[Side.Front];
vIndex[Side.Bottom] = vIndex[Side.Back] + vCount[Side.Back]; vIndex[Side.Bottom] = vIndex[Side.Back] + vCount[Side.Back];
vIndex[Side.Top] = vIndex[Side.Bottom] + vCount[Side.Bottom]; vIndex[Side.Top] = vIndex[Side.Bottom] + vCount[Side.Bottom];
offset += VerticesCount();
} }
public void ResetState() { public void ResetState() {
@ -92,10 +88,27 @@ namespace ClassicalSharp {
} }
} }
protected virtual void PostStretchTiles(int x1, int y1, int z1) { int TotalVerticesCount() {
int vertsCount = 0;
for (int i = 0; i < normalParts.Length; i++) { for (int i = 0; i < normalParts.Length; i++) {
normalParts[i].ExpandToCapacity(); vertsCount += normalParts[i].VerticesCount();
translucentParts[i].ExpandToCapacity(); vertsCount += translucentParts[i].VerticesCount();
}
return vertsCount;
}
protected virtual void PostStretchTiles(int x1, int y1, int z1) {
int vertsCount = TotalVerticesCount();
if (vertices == null || (vertsCount + 2) > vertices.Length) {
vertices = new VertexP3fT2fC4b[vertsCount + 2];
// ensure buffer is up to 64 bits aligned for last element
}
// organised as: all N_0, all T_0, all N_1, all T1, etc
vertsCount = 0;
for (int i = 0; i < normalParts.Length; i++) {
normalParts[i].CalcOffsets(ref vertsCount);
translucentParts[i].CalcOffsets(ref vertsCount);
} }
} }
@ -142,31 +155,31 @@ namespace ClassicalSharp {
// Draw Z axis // Draw Z axis
int index = part.sIndex; int index = part.sIndex;
v.X = x1; v.Y = y1; v.Z = z1; v.U = u2; v.V = v2; part.vertices[index + 0] = v; v.X = x1; v.Y = y1; v.Z = z1; v.U = u2; v.V = v2; vertices[index + 0] = v;
v.Y = y2; v.V = v1; part.vertices[index + 1] = v; v.Y = y2; v.V = v1; vertices[index + 1] = v;
v.X = x2; v.Z = z2; v.U = u1; part.vertices[index + 2] = v; v.X = x2; v.Z = z2; v.U = u1; vertices[index + 2] = v;
v.Y = y1; v.V = v2; part.vertices[index + 3] = v; v.Y = y1; v.V = v2; vertices[index + 3] = v;
// Draw Z axis mirrored // Draw Z axis mirrored
index += part.sAdvance; index += part.sAdvance;
v.X = x2; v.Y = y1; v.Z = z2; v.U = u2; part.vertices[index + 0] = v; v.X = x2; v.Y = y1; v.Z = z2; v.U = u2; vertices[index + 0] = v;
v.Y = y2; v.V = v1; part.vertices[index + 1] = v; v.Y = y2; v.V = v1; vertices[index + 1] = v;
v.X = x1; v.Z = z1; v.U = u1; part.vertices[index + 2] = v; v.X = x1; v.Z = z1; v.U = u1; vertices[index + 2] = v;
v.Y = y1; v.V = v2; part.vertices[index + 3] = v; v.Y = y1; v.V = v2; vertices[index + 3] = v;
// Draw X axis // Draw X axis
index += part.sAdvance; index += part.sAdvance;
v.X = x1; v.Y = y1; v.Z = z2; v.U = u2; part.vertices[index + 0] = v; v.X = x1; v.Y = y1; v.Z = z2; v.U = u2; vertices[index + 0] = v;
v.Y = y2; v.V = v1; part.vertices[index + 1] = v; v.Y = y2; v.V = v1; vertices[index + 1] = v;
v.X = x2; v.Z = z1; v.U = u1; part.vertices[index + 2] = v; v.X = x2; v.Z = z1; v.U = u1; vertices[index + 2] = v;
v.Y = y1; v.V = v2; part.vertices[index + 3] = v; v.Y = y1; v.V = v2; vertices[index + 3] = v;
// Draw X axis mirrored // Draw X axis mirrored
index += part.sAdvance; index += part.sAdvance;
v.X = x2; v.Y = y1; v.Z = z1; v.U = u2; part.vertices[index + 0] = v; v.X = x2; v.Y = y1; v.Z = z1; v.U = u2; vertices[index + 0] = v;
v.Y = y2; v.V = v1; part.vertices[index + 1] = v; v.Y = y2; v.V = v1; vertices[index + 1] = v;
v.X = x1; v.Z = z2; v.U = u1; part.vertices[index + 2] = v; v.X = x1; v.Z = z2; v.U = u1; vertices[index + 2] = v;
v.Y = y1; v.V = v2; part.vertices[index + 3] = v; v.Y = y1; v.V = v2; vertices[index + 3] = v;
part.sIndex += 4; part.sIndex += 4;
} }

View File

@ -231,12 +231,12 @@ namespace ClassicalSharp.Renderers {
info.OcclusionFlags = 0; info.OcclusionFlags = 0;
info.OccludedFlags = 0; info.OccludedFlags = 0;
#endif #endif
game.Graphics.DeleteVb(ref info.VbId);
if (info.NormalParts != null) { if (info.NormalParts != null) {
ChunkPartInfo[] parts = info.NormalParts; ChunkPartInfo[] parts = info.NormalParts;
for (int i = 0; i < parts.Length; i++) { for (int i = 0; i < parts.Length; i++) {
game.Graphics.DeleteVb(ref parts[i].VbId); if (parts[i].Offset < 0) continue;
if (parts[i].VerticesCount == 0) continue;
renderer.normalPartsCount[i]--; renderer.normalPartsCount[i]--;
} }
info.NormalParts = null; info.NormalParts = null;
@ -245,8 +245,7 @@ namespace ClassicalSharp.Renderers {
if (info.TranslucentParts != null) { if (info.TranslucentParts != null) {
ChunkPartInfo[] parts = info.TranslucentParts; ChunkPartInfo[] parts = info.TranslucentParts;
for (int i = 0; i < parts.Length; i++) { for (int i = 0; i < parts.Length; i++) {
game.Graphics.DeleteVb(ref parts[i].VbId); if (parts[i].Offset < 0) continue;
if (parts[i].VerticesCount == 0) continue;
renderer.translucentPartsCount[i]--; renderer.translucentPartsCount[i]--;
} }
info.TranslucentParts = null; info.TranslucentParts = null;
@ -360,14 +359,14 @@ namespace ClassicalSharp.Renderers {
if (info.NormalParts != null) { if (info.NormalParts != null) {
ChunkPartInfo[] parts = info.NormalParts; ChunkPartInfo[] parts = info.NormalParts;
for (int i = 0; i < parts.Length; i++) { for (int i = 0; i < parts.Length; i++) {
if (parts[i].VerticesCount == 0) continue; if (parts[i].Offset < 0) continue;
renderer.normalPartsCount[i]++; renderer.normalPartsCount[i]++;
} }
} }
if (info.TranslucentParts != null) { if (info.TranslucentParts != null) {
ChunkPartInfo[] parts = info.TranslucentParts; ChunkPartInfo[] parts = info.TranslucentParts;
for (int i = 0; i < parts.Length; i++) { for (int i = 0; i < parts.Length; i++) {
if (parts[i].VerticesCount == 0) continue; if (parts[i].Offset < 0) continue;
renderer.translucentPartsCount[i]++; renderer.translucentPartsCount[i]++;
} }
} }

View File

@ -11,7 +11,7 @@ using BlockID = System.UInt16;
namespace ClassicalSharp.Renderers { namespace ClassicalSharp.Renderers {
public struct ChunkPartInfo { public struct ChunkPartInfo {
public int VbId, VerticesCount, SpriteCount; public int Offset, SpriteCount;
public ushort LeftCount, RightCount, FrontCount, BackCount, BottomCount, TopCount; public ushort LeftCount, RightCount, FrontCount, BackCount, BottomCount, TopCount;
} }
@ -25,6 +25,7 @@ namespace ClassicalSharp.Renderers {
public bool Visited = false, Occluded = false; public bool Visited = false, Occluded = false;
public byte OcclusionFlags, OccludedFlags, DistanceFlags; public byte OcclusionFlags, OccludedFlags, DistanceFlags;
#endif #endif
public int VbId;
public ChunkPartInfo[] NormalParts; public ChunkPartInfo[] NormalParts;
public ChunkPartInfo[] TranslucentParts; public ChunkPartInfo[] TranslucentParts;
@ -42,7 +43,7 @@ namespace ClassicalSharp.Renderers {
} }
} }
public partial class MapRenderer { public partial class MapRenderer {
Game game; Game game;
internal int _1DUsed = -1, chunksX, chunksY, chunksZ; internal int _1DUsed = -1, chunksX, chunksY, chunksZ;
@ -177,10 +178,10 @@ namespace ClassicalSharp.Renderers {
if (info.NormalParts == null) continue; if (info.NormalParts == null) continue;
ChunkPartInfo part = info.NormalParts[batch]; ChunkPartInfo part = info.NormalParts[batch];
if (part.VerticesCount == 0) continue; if (part.Offset < 0) continue;
usedNormal[batch] = true; usedNormal[batch] = true;
gfx.BindVb(part.VbId); gfx.BindVb(info.VbId);
bool drawLeft = info.DrawLeft && part.LeftCount > 0; bool drawLeft = info.DrawLeft && part.LeftCount > 0;
bool drawRight = info.DrawRight && part.RightCount > 0; bool drawRight = info.DrawRight && part.RightCount > 0;
bool drawBottom = info.DrawBottom && part.BottomCount > 0; bool drawBottom = info.DrawBottom && part.BottomCount > 0;
@ -188,7 +189,7 @@ namespace ClassicalSharp.Renderers {
bool drawFront = info.DrawFront && part.FrontCount > 0; bool drawFront = info.DrawFront && part.FrontCount > 0;
bool drawBack = info.DrawBack && part.BackCount > 0; bool drawBack = info.DrawBack && part.BackCount > 0;
int offset = part.SpriteCount; int offset = part.Offset + part.SpriteCount;
if (drawLeft && drawRight) { if (drawLeft && drawRight) {
gfx.FaceCulling = true; gfx.FaceCulling = true;
gfx.DrawIndexedVb_TrisT2fC4b(part.LeftCount + part.RightCount, offset); gfx.DrawIndexedVb_TrisT2fC4b(part.LeftCount + part.RightCount, offset);
@ -231,20 +232,25 @@ namespace ClassicalSharp.Renderers {
} }
if (part.SpriteCount == 0) continue; if (part.SpriteCount == 0) continue;
offset = part.Offset;
int count = part.SpriteCount / 4; // 4 per sprite int count = part.SpriteCount / 4; // 4 per sprite
gfx.FaceCulling = true; gfx.FaceCulling = true;
if (info.DrawRight || info.DrawFront) { if (info.DrawRight || info.DrawFront) {
gfx.DrawIndexedVb_TrisT2fC4b(count, 0); game.Vertices += count; gfx.DrawIndexedVb_TrisT2fC4b(count, offset); game.Vertices += count;
} } offset += count;
if (info.DrawLeft || info.DrawBack) { if (info.DrawLeft || info.DrawBack) {
gfx.DrawIndexedVb_TrisT2fC4b(count, count); game.Vertices += count; gfx.DrawIndexedVb_TrisT2fC4b(count, offset); game.Vertices += count;
} } offset += count;
if (info.DrawLeft || info.DrawFront) { if (info.DrawLeft || info.DrawFront) {
gfx.DrawIndexedVb_TrisT2fC4b(count, count * 2); game.Vertices += count; gfx.DrawIndexedVb_TrisT2fC4b(count, offset); game.Vertices += count;
} } offset += count;
if (info.DrawRight || info.DrawBack) { if (info.DrawRight || info.DrawBack) {
gfx.DrawIndexedVb_TrisT2fC4b(count, count * 3); game.Vertices += count; gfx.DrawIndexedVb_TrisT2fC4b(count, offset); game.Vertices += count;
} } offset += count;
gfx.FaceCulling = false; gfx.FaceCulling = false;
} }
} }
@ -256,10 +262,10 @@ namespace ClassicalSharp.Renderers {
if (info.TranslucentParts == null) continue; if (info.TranslucentParts == null) continue;
ChunkPartInfo part = info.TranslucentParts[batch]; ChunkPartInfo part = info.TranslucentParts[batch];
if (part.VerticesCount == 0) continue; if (part.Offset < 0) continue;
usedTranslucent[batch] = true; usedTranslucent[batch] = true;
gfx.BindVb(part.VbId); gfx.BindVb(info.VbId);
bool drawLeft = (inTranslucent || info.DrawLeft) && part.LeftCount > 0; bool drawLeft = (inTranslucent || info.DrawLeft) && part.LeftCount > 0;
bool drawRight = (inTranslucent || info.DrawRight) && part.RightCount > 0; bool drawRight = (inTranslucent || info.DrawRight) && part.RightCount > 0;
bool drawBottom = (inTranslucent || info.DrawBottom) && part.BottomCount > 0; bool drawBottom = (inTranslucent || info.DrawBottom) && part.BottomCount > 0;
@ -267,7 +273,7 @@ namespace ClassicalSharp.Renderers {
bool drawFront = (inTranslucent || info.DrawFront) && part.FrontCount > 0; bool drawFront = (inTranslucent || info.DrawFront) && part.FrontCount > 0;
bool drawBack = (inTranslucent || info.DrawBack) && part.BackCount > 0; bool drawBack = (inTranslucent || info.DrawBack) && part.BackCount > 0;
int offset = 0; int offset = part.Offset;
if (drawLeft && drawRight) { if (drawLeft && drawRight) {
gfx.DrawIndexedVb_TrisT2fC4b(part.LeftCount + part.RightCount, offset); gfx.DrawIndexedVb_TrisT2fC4b(part.LeftCount + part.RightCount, offset);
game.Vertices += (part.LeftCount + part.RightCount); game.Vertices += (part.LeftCount + part.RightCount);

View File

@ -40,51 +40,39 @@ typedef struct Builder1DPart_ {
VertexP3fT2fC4b* fVertices[FACE_COUNT]; VertexP3fT2fC4b* fVertices[FACE_COUNT];
Int32 fCount[FACE_COUNT]; Int32 fCount[FACE_COUNT];
Int32 sCount, sOffset, sAdvance; Int32 sCount, sOffset, sAdvance;
VertexP3fT2fC4b* vertices;
Int32 verticesBufferCount;
} Builder1DPart; } Builder1DPart;
/* Part builder data, for both normal and translucent parts. /* Part builder data, for both normal and translucent parts.
The first ATLAS1D_MAX_ATLASES_COUNT parts are for normal parts, remainder are for translucent parts. */ The first ATLAS1D_MAX_ATLASES_COUNT parts are for normal parts, remainder are for translucent parts. */
Builder1DPart Builder_Parts[ATLAS1D_MAX_ATLASES_COUNT * 2]; Builder1DPart Builder_Parts[ATLAS1D_MAX_ATLASES_COUNT * 2];
VertexP3fT2fC4b* Builder_Vertices;
Int32 Builder_VerticesElems;
static Int32 Builder1DPart_VerticesCount(Builder1DPart* part) { static Int32 Builder1DPart_VerticesCount(Builder1DPart* part) {
Int32 count = part->sCount; Int32 i, count = part->sCount;
Int32 i;
for (i = 0; i < FACE_COUNT; i++) { count += part->fCount[i]; } for (i = 0; i < FACE_COUNT; i++) { count += part->fCount[i]; }
return count; return count;
} }
static void Builder1DPart_Prepare(Builder1DPart* part) { static void Builder1DPart_CalcOffsets(Builder1DPart* part, Int32* offset) {
part->sOffset = 0; Int32 pos = *offset, i;
part->sAdvance = (part->sCount / 4); part->sOffset = pos;
part->sAdvance = part->sCount >> 2;
/* ensure buffer can be accessed with 64 bytes alignment by putting 2 extra vertices at end. */ pos += part->sCount;
Int32 vCount = Builder1DPart_VerticesCount(part);
if (vCount > part->verticesBufferCount) {
Platform_MemFree(&part->vertices);
part->vertices = Platform_MemAlloc(vCount + 2, sizeof(VertexP3fT2fC4b));
part->verticesBufferCount = vCount;
if (part->vertices == NULL) {
ErrorHandler_Fail("Builder1DPart_Prepare - failed to allocate memory");
}
}
Int32 offset = part->sCount, i;
for (i = 0; i < FACE_COUNT; i++) { for (i = 0; i < FACE_COUNT; i++) {
part->fVertices[i] = &part->vertices[offset]; part->fVertices[i] = &Builder_Vertices[pos];
offset += part->fCount[i]; pos += part->fCount[i];
} }
*offset = pos;
} }
static void Builder1DPart_Reset(Builder1DPart* part) { static Int32 Builder_TotalVerticesCount(void) {
part->sCount = 0; part->sOffset = 0; part->sAdvance = 0; Int32 i, count = 0;
for (i = 0; i < ATLAS1D_MAX_ATLASES_COUNT * 2; i++) {
Int32 i; count += Builder1DPart_VerticesCount(&Builder_Parts[i]);
for (i = 0; i < FACE_COUNT; i++) {
part->fVertices[i] = NULL;
part->fCount[i] = 0;
} }
return count;
} }
@ -101,22 +89,22 @@ static void Builder_AddVertices(BlockID block, Face face) {
part->fCount[face] += 4; part->fCount[face] += 4;
} }
static void Builder_SetPartInfo(Builder1DPart* part, ChunkPartInfo* info, bool* hasParts) { static void Builder_SetPartInfo(Builder1DPart* part, Int32* offset, ChunkPartInfo* info, bool* hasParts) {
Int32 vCount = Builder1DPart_VerticesCount(part); Int32 vCount = Builder1DPart_VerticesCount(part);
info->Offset = -1;
if (vCount == 0) return; if (vCount == 0) return;
/* add an extra element to fix crashing on some GPUs */ info->Offset = *offset;
info->VbId = Gfx_CreateVb(part->vertices, VERTEX_FORMAT_P3FT2FC4B, vCount + 1); *offset += vCount;
info->HasVertices = true;
*hasParts = true; *hasParts = true;
info->XMinCount = (UInt16)part->fCount[FACE_XMIN]; info->Counts[FACE_XMIN] = part->fCount[FACE_XMIN];
info->XMaxCount = (UInt16)part->fCount[FACE_XMAX]; info->Counts[FACE_XMAX] = part->fCount[FACE_XMAX];
info->ZMinCount = (UInt16)part->fCount[FACE_ZMIN]; info->Counts[FACE_ZMIN] = part->fCount[FACE_ZMIN];
info->ZMaxCount = (UInt16)part->fCount[FACE_ZMAX]; info->Counts[FACE_ZMAX] = part->fCount[FACE_ZMAX];
info->YMinCount = (UInt16)part->fCount[FACE_YMIN]; info->Counts[FACE_YMIN] = part->fCount[FACE_YMIN];
info->YMaxCount = (UInt16)part->fCount[FACE_YMAX]; info->Counts[FACE_YMAX] = part->fCount[FACE_YMAX];
info->SpriteCountDiv4 = part->sCount >> 2; info->SpriteCount = part->sCount;
} }
@ -326,15 +314,20 @@ void Builder_MakeChunk(ChunkInfo* info) {
info->AllAir = allAir; info->AllAir = allAir;
if (!hasMesh) return; if (!hasMesh) return;
Int32 i, partsIndex = MapRenderer_Pack(x >> CHUNK_SHIFT, y >> CHUNK_SHIFT, z >> CHUNK_SHIFT); Int32 totalVerts = Builder_TotalVerticesCount();
if (totalVerts == 0) return;
/* add an extra element to fix crashing on some GPUs */
info->VbId = Gfx_CreateVb(Builder_Vertices, VERTEX_FORMAT_P3FT2FC4B, totalVerts + 1);
Int32 i, offset = 0, partsIndex = MapRenderer_Pack(x >> CHUNK_SHIFT, y >> CHUNK_SHIFT, z >> CHUNK_SHIFT);
bool hasNormal = false, hasTranslucent = false; bool hasNormal = false, hasTranslucent = false;
for (i = 0; i < Atlas1D_Count; i++) { for (i = 0; i < MapRenderer_1DUsedCount; i++) {
Int32 j = i + ATLAS1D_MAX_ATLASES_COUNT; Int32 j = i + ATLAS1D_MAX_ATLASES_COUNT;
Int32 curIdx = partsIndex + i * MapRenderer_ChunksCount; Int32 curIdx = partsIndex + i * MapRenderer_ChunksCount;
Builder_SetPartInfo(&Builder_Parts[i], &MapRenderer_PartsNormal[curIdx], &hasNormal); Builder_SetPartInfo(&Builder_Parts[i], &offset, &MapRenderer_PartsNormal[curIdx], &hasNormal);
Builder_SetPartInfo(&Builder_Parts[j], &MapRenderer_PartsTranslucent[curIdx], &hasTranslucent); Builder_SetPartInfo(&Builder_Parts[j], &offset, &MapRenderer_PartsTranslucent[curIdx], &hasTranslucent);
} }
if (hasNormal) { if (hasNormal) {
@ -361,18 +354,27 @@ static bool Builder_OccludedLiquid(Int32 chunkIndex) {
} }
static void Builder_DefaultPreStretchTiles(Int32 x1, Int32 y1, Int32 z1) { static void Builder_DefaultPreStretchTiles(Int32 x1, Int32 y1, Int32 z1) {
Int32 i; Platform_MemSet(Builder_Parts, 0, sizeof(Builder_Parts));
for (i = 0; i < ATLAS1D_MAX_ATLASES_COUNT * 2; i++) {
Builder1DPart_Reset(&Builder_Parts[i]);
}
} }
static void Builder_DefaultPostStretchTiles(Int32 x1, Int32 y1, Int32 z1) { static void Builder_DefaultPostStretchTiles(Int32 x1, Int32 y1, Int32 z1) {
Int32 i; Int32 i, vertsCount = Builder_TotalVerticesCount();
for (i = 0; i < ATLAS1D_MAX_ATLASES_COUNT * 2; i++) { if (vertsCount > Builder_VerticesElems) {
Int32 vCount = Builder1DPart_VerticesCount(&Builder_Parts[i]); Platform_MemFree(&Builder_Vertices);
if (vCount == 0) continue; /* ensure buffer can be accessed with 64 bytes alignment by putting 2 extra vertices at end. */
Builder1DPart_Prepare(&Builder_Parts[i]); Builder_Vertices = Platform_MemAlloc(vertsCount + 2, sizeof(VertexP3fT2fC4b));
Builder_VerticesElems = vertsCount;
if (Builder_Vertices == NULL) {
ErrorHandler_Fail("Builder1DPart_Prepare - failed to allocate memory");
}
}
vertsCount = 0;
for (i = 0; i < ATLAS1D_MAX_ATLASES_COUNT; i++) {
Int32 j = i + ATLAS1D_MAX_ATLASES_COUNT;
Builder1DPart_CalcOffsets(&Builder_Parts[i], &vertsCount);
Builder1DPart_CalcOffsets(&Builder_Parts[j], &vertsCount);
} }
} }
@ -410,31 +412,31 @@ static void Builder_DrawSprite(Int32 count) {
/* Draw Z axis */ /* Draw Z axis */
Int32 index = part->sOffset; Int32 index = part->sOffset;
v.X = x1; v.Y = y1; v.Z = z1; v.U = u2; v.V = v2; part->vertices[index + 0] = v; v.X = x1; v.Y = y1; v.Z = z1; v.U = u2; v.V = v2; Builder_Vertices[index + 0] = v;
v.Y = y2; v.V = v1; part->vertices[index + 1] = v; v.Y = y2; v.V = v1; Builder_Vertices[index + 1] = v;
v.X = x2; v.Z = z2; v.U = u1; part->vertices[index + 2] = v; v.X = x2; v.Z = z2; v.U = u1; Builder_Vertices[index + 2] = v;
v.Y = y1; v.V = v2; part->vertices[index + 3] = v; v.Y = y1; v.V = v2; Builder_Vertices[index + 3] = v;
/* Draw Z axis mirrored */ /* Draw Z axis mirrored */
index += part->sAdvance; index += part->sAdvance;
v.X = x2; v.Y = y1; v.Z = z2; v.U = u2; part->vertices[index + 0] = v; v.X = x2; v.Y = y1; v.Z = z2; v.U = u2; Builder_Vertices[index + 0] = v;
v.Y = y2; v.V = v1; part->vertices[index + 1] = v; v.Y = y2; v.V = v1; Builder_Vertices[index + 1] = v;
v.X = x1; v.Z = z1; v.U = u1; part->vertices[index + 2] = v; v.X = x1; v.Z = z1; v.U = u1; Builder_Vertices[index + 2] = v;
v.Y = y1; v.V = v2; part->vertices[index + 3] = v; v.Y = y1; v.V = v2; Builder_Vertices[index + 3] = v;
/* Draw X axis */ /* Draw X axis */
index += part->sAdvance; index += part->sAdvance;
v.X = x1; v.Y = y1; v.Z = z2; v.U = u2; part->vertices[index + 0] = v; v.X = x1; v.Y = y1; v.Z = z2; v.U = u2; Builder_Vertices[index + 0] = v;
v.Y = y2; v.V = v1; part->vertices[index + 1] = v; v.Y = y2; v.V = v1; Builder_Vertices[index + 1] = v;
v.X = x2; v.Z = z1; v.U = u1; part->vertices[index + 2] = v; v.X = x2; v.Z = z1; v.U = u1; Builder_Vertices[index + 2] = v;
v.Y = y1; v.V = v2; part->vertices[index + 3] = v; v.Y = y1; v.V = v2; Builder_Vertices[index + 3] = v;
/* Draw X axis mirrored */ /* Draw X axis mirrored */
index += part->sAdvance; index += part->sAdvance;
v.X = x2; v.Y = y1; v.Z = z1; v.U = u2; part->vertices[index + 0] = v; v.X = x2; v.Y = y1; v.Z = z1; v.U = u2; Builder_Vertices[index + 0] = v;
v.Y = y2; v.V = v1; part->vertices[index + 1] = v; v.Y = y2; v.V = v1; Builder_Vertices[index + 1] = v;
v.X = x1; v.Z = z2; v.U = u1; part->vertices[index + 2] = v; v.X = x1; v.Z = z2; v.U = u1; Builder_Vertices[index + 2] = v;
v.Y = y1; v.V = v2; part->vertices[index + 3] = v; v.Y = y1; v.V = v2; Builder_Vertices[index + 3] = v;
part->sOffset += 4; part->sOffset += 4;
} }
@ -643,7 +645,7 @@ static void NormalBuilder_RenderBlock(Int32 index) {
void NormalBuilder_SetActive(void) { void NormalBuilder_SetActive(void) {
Builder_SetDefault(); Builder_SetDefault();
Builder_StretchXLiquid = NormalBuilder_StretchXLiquid; Builder_StretchXLiquid = NormalBuilder_StretchXLiquid;
Builder_StretchX = NormalBuilder_StretchX; Builder_StretchX = NormalBuilder_StretchX;
Builder_StretchZ = NormalBuilder_StretchZ; Builder_StretchZ = NormalBuilder_StretchZ;
Builder_RenderBlock = NormalBuilder_RenderBlock; Builder_RenderBlock = NormalBuilder_RenderBlock;
} }

View File

@ -13,11 +13,16 @@
#include "Builder.h" #include "Builder.h"
#include "Utils.h" #include "Utils.h"
#include "ErrorHandler.h" #include "ErrorHandler.h"
#include "Vectors.h"
Vector3I ChunkUpdater_ChunkPos;
UInt32* ChunkUpdater_Distances;
void ChunkInfo_Reset(ChunkInfo* chunk, Int32 x, Int32 y, Int32 z) { void ChunkInfo_Reset(ChunkInfo* chunk, Int32 x, Int32 y, Int32 z) {
chunk->CentreX = (UInt16)(x + 8); chunk->CentreX = (UInt16)(x + 8);
chunk->CentreY = (UInt16)(y + 8); chunk->CentreY = (UInt16)(y + 8);
chunk->CentreZ = (UInt16)(z + 8); chunk->CentreZ = (UInt16)(z + 8);
chunk->VbId = NULL;
chunk->Visible = true; chunk->Empty = false; chunk->Visible = true; chunk->Empty = false;
chunk->PendingDelete = false; chunk->AllAir = false; chunk->PendingDelete = false; chunk->AllAir = false;
@ -340,36 +345,30 @@ static void ChunkUpdater_ClearChunkCache_Handler(void* obj) {
} }
#define ChunkUpdater_DeleteParts(parts, partsCount)\
if (parts != NULL) {\
ChunkPartInfo* ptr = parts;\
for (i = 0; i < MapRenderer_1DUsedCount; i++) {\
Gfx_DeleteVb(&ptr->VbId);\
if (ptr->HasVertices) { partsCount[i]--; }\
ptr += MapRenderer_ChunksCount;\
}\
parts = NULL;\
}
void ChunkUpdater_DeleteChunk(ChunkInfo* info) { void ChunkUpdater_DeleteChunk(ChunkInfo* info) {
info->Empty = false; info->AllAir = false; info->Empty = false; info->AllAir = false;
#if OCCLUSION #if OCCLUSION
info.OcclusionFlags = 0; info.OcclusionFlags = 0;
info.OccludedFlags = 0; info.OccludedFlags = 0;
#endif #endif
Gfx_DeleteVb(&info->VbId);
Int32 i; Int32 i;
ChunkUpdater_DeleteParts(info->NormalParts, MapRenderer_NormalPartsCount);
ChunkUpdater_DeleteParts(info->TranslucentParts, MapRenderer_TranslucentPartsCount);
}
#define ChunkUpdater_AddParts(parts, partsCount)\ if (info->NormalParts != NULL) {
if (parts != NULL) {\ ChunkPartInfo* ptr = info->NormalParts;
ChunkPartInfo* ptr = parts;\ for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) {
for (i = 0; i < MapRenderer_1DUsedCount; i++) {\ if (ptr->Offset >= 0) { MapRenderer_NormalPartsCount[i]--; }
if (ptr->HasVertices) { partsCount[i]++; }\ }
ptr += MapRenderer_ChunksCount;\ info->NormalParts = NULL;
}\ }
if (info->TranslucentParts != NULL) {
ChunkPartInfo* ptr = info->TranslucentParts;
for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) {
if (ptr->Offset >= 0) { MapRenderer_TranslucentPartsCount[i]--; }
}
info->TranslucentParts = NULL;
}
} }
void ChunkUpdater_BuildChunk(ChunkInfo* info, Int32* chunkUpdates) { void ChunkUpdater_BuildChunk(ChunkInfo* info, Int32* chunkUpdates) {
@ -382,10 +381,21 @@ void ChunkUpdater_BuildChunk(ChunkInfo* info, Int32* chunkUpdates) {
info->Empty = true; info->Empty = true;
return; return;
} }
Int32 i; Int32 i;
ChunkUpdater_AddParts(info->NormalParts, MapRenderer_NormalPartsCount);
ChunkUpdater_AddParts(info->TranslucentParts, MapRenderer_TranslucentPartsCount); if (info->NormalParts != NULL) {
ChunkPartInfo* ptr = info->NormalParts;
for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) {
if (ptr->Offset >= 0) { MapRenderer_NormalPartsCount[i]++; }
}
}
if (info->TranslucentParts != NULL) {
ChunkPartInfo* ptr = info->TranslucentParts;
for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) {
if (ptr->Offset >= 0) { MapRenderer_TranslucentPartsCount[i]++; }
}
}
} }
static void ChunkUpdater_QuickSort(Int32 left, Int32 right) { static void ChunkUpdater_QuickSort(Int32 left, Int32 right) {

View File

@ -1,6 +1,7 @@
#ifndef CC_CHUNKUPDATER_H #ifndef CC_CHUNKUPDATER_H
#define CC_CHUNKUPDATER_H #define CC_CHUNKUPDATER_H
#include "Vectors.h" #include "Typedefs.h"
#include "Constants.h"
/* Manages the process of building/deleting chunk meshes. /* Manages the process of building/deleting chunk meshes.
Also sorts chunks so nearest chunks are ordered first, and calculates chunk visibility. Also sorts chunks so nearest chunks are ordered first, and calculates chunk visibility.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
@ -8,10 +9,9 @@
/* Describes a portion of the data needed for rendering a chunk. */ /* Describes a portion of the data needed for rendering a chunk. */
typedef struct ChunkPartInfo_ { typedef struct ChunkPartInfo_ {
GfxResourceID VbId; Int32 Offset; /* -1 if no vertices at all */
UInt16 HasVertices; /* Does this chunk have any vertices at all? */ Int32 SpriteCount; /* Sprite vertices count */
UInt16 SpriteCountDiv4; /* Sprite vertices count, divided by 4 */ UInt16 Counts[FACE_COUNT]; /* Counts per face */
UInt16 XMinCount, XMaxCount, ZMinCount, ZMaxCount, YMinCount, YMaxCount; /* Counts per face */
} ChunkPartInfo; } ChunkPartInfo;
/* Describes data necessary for rendering a chunk. */ /* Describes data necessary for rendering a chunk. */
@ -35,13 +35,12 @@ typedef struct ChunkInfo_ {
public bool Visited = false, Occluded = false; public bool Visited = false, Occluded = false;
public byte OcclusionFlags, OccludedFlags, DistanceFlags; public byte OcclusionFlags, OccludedFlags, DistanceFlags;
#endif #endif
GfxResourceID VbId;
ChunkPartInfo* NormalParts; ChunkPartInfo* NormalParts;
ChunkPartInfo* TranslucentParts; ChunkPartInfo* TranslucentParts;
} ChunkInfo; } ChunkInfo;
void ChunkInfo_Reset(ChunkInfo* chunk, Int32 x, Int32 y, Int32 z); void ChunkInfo_Reset(ChunkInfo* chunk, Int32 x, Int32 y, Int32 z);
Vector3I ChunkUpdater_ChunkPos;
UInt32* ChunkUpdater_Distances;
void ChunkUpdater_Init(void); void ChunkUpdater_Init(void);
void ChunkUpdater_Free(void); void ChunkUpdater_Free(void);

View File

@ -45,73 +45,78 @@ static void MapRenderer_RenderNormalBatch(UInt32 batch) {
if (info->NormalParts == NULL) continue; if (info->NormalParts == NULL) continue;
ChunkPartInfo part = *(info->NormalParts + offset); ChunkPartInfo part = *(info->NormalParts + offset);
if (!part.HasVertices) continue; if (part.Offset < 0) continue;
MapRenderer_HasNormalParts[batch] = true; MapRenderer_HasNormalParts[batch] = true;
Gfx_BindVb(part.VbId); Gfx_BindVb(info->VbId);
bool drawXMin = info->DrawXMin && part.XMinCount > 0; bool drawXMin = info->DrawXMin && part.Counts[FACE_XMIN];
bool drawXMax = info->DrawXMax && part.XMaxCount > 0; bool drawXMax = info->DrawXMax && part.Counts[FACE_XMAX];
bool drawYMin = info->DrawYMin && part.YMinCount > 0; bool drawYMin = info->DrawYMin && part.Counts[FACE_YMIN];
bool drawYMax = info->DrawYMax && part.YMaxCount > 0; bool drawYMax = info->DrawYMax && part.Counts[FACE_YMAX];
bool drawZMin = info->DrawZMin && part.ZMinCount > 0; bool drawZMin = info->DrawZMin && part.Counts[FACE_ZMIN];
bool drawZMax = info->DrawZMax && part.ZMaxCount > 0; bool drawZMax = info->DrawZMax && part.Counts[FACE_ZMAX];
UInt32 offset = part.SpriteCountDiv4 << 2; Int32 offset = part.Offset + part.SpriteCount;
if (drawXMin && drawXMax) { if (drawXMin && drawXMax) {
Gfx_SetFaceCulling(true); Gfx_SetFaceCulling(true);
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMinCount + part.XMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX], offset);
Gfx_SetFaceCulling(false); Gfx_SetFaceCulling(false);
Game_Vertices += part.XMinCount + part.XMaxCount; Game_Vertices += part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX];
} else if (drawXMin) { } else if (drawXMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMIN], offset);
Game_Vertices += part.XMinCount; Game_Vertices += part.Counts[FACE_XMIN];
} else if (drawXMax) { } else if (drawXMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMaxCount, offset + part.XMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMAX], offset + part.Counts[FACE_XMIN]);
Game_Vertices += part.XMaxCount; Game_Vertices += part.Counts[FACE_XMAX];
} }
offset += part.XMinCount + part.XMaxCount; offset += part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX];
if (drawZMin && drawZMax) { if (drawZMin && drawZMax) {
Gfx_SetFaceCulling(true); Gfx_SetFaceCulling(true);
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMinCount + part.ZMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX], offset);
Gfx_SetFaceCulling(false); Gfx_SetFaceCulling(false);
Game_Vertices += part.ZMinCount + part.ZMaxCount; Game_Vertices += part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX];
} else if (drawZMin) { } else if (drawZMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMIN], offset);
Game_Vertices += part.ZMinCount; Game_Vertices += part.Counts[FACE_ZMIN];
} else if (drawZMax) { } else if (drawZMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMaxCount, offset + part.ZMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMAX], offset + part.Counts[FACE_ZMIN]);
Game_Vertices += part.ZMaxCount; Game_Vertices += part.Counts[FACE_ZMAX];
} }
offset += part.ZMinCount + part.ZMaxCount; offset += part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX];
if (drawYMin && drawYMax) { if (drawYMin && drawYMax) {
Gfx_SetFaceCulling(true); Gfx_SetFaceCulling(true);
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMinCount + part.YMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMIN] + part.Counts[FACE_YMAX], offset);
Gfx_SetFaceCulling(false); Gfx_SetFaceCulling(false);
Game_Vertices += part.YMaxCount + part.YMinCount; Game_Vertices += part.Counts[FACE_YMAX] + part.Counts[FACE_YMIN];
} else if (drawYMin) { } else if (drawYMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMIN], offset);
Game_Vertices += part.YMinCount; Game_Vertices += part.Counts[FACE_YMIN];
} else if (drawYMax) { } else if (drawYMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMaxCount, offset + part.YMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMAX], offset + part.Counts[FACE_YMIN]);
Game_Vertices += part.YMaxCount; Game_Vertices += part.Counts[FACE_YMAX];
} }
if (part.SpriteCountDiv4 == 0) continue; if (part.SpriteCount == 0) continue;
UInt32 count = part.SpriteCountDiv4; /* 4 per sprite */ offset = part.Offset;
Int32 count = part.SpriteCount >> 2; /* 4 per sprite */
Gfx_SetFaceCulling(true); Gfx_SetFaceCulling(true);
if (info->DrawXMax || info->DrawZMin) { if (info->DrawXMax || info->DrawZMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(count, 0); Game_Vertices += count; Gfx_DrawIndexedVb_TrisT2fC4b(count, offset); Game_Vertices += count;
} } offset += count;
if (info->DrawXMin || info->DrawZMax) { if (info->DrawXMin || info->DrawZMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(count, count); Game_Vertices += count; Gfx_DrawIndexedVb_TrisT2fC4b(count, offset); Game_Vertices += count;
} } offset += count;
if (info->DrawXMin || info->DrawZMin) { if (info->DrawXMin || info->DrawZMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(count, count * 2); Game_Vertices += count; Gfx_DrawIndexedVb_TrisT2fC4b(count, offset); Game_Vertices += count;
} } offset += count;
if (info->DrawXMax || info->DrawZMax) { if (info->DrawXMax || info->DrawZMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(count, count * 3); Game_Vertices += count; Gfx_DrawIndexedVb_TrisT2fC4b(count, offset); Game_Vertices += count;
} }
Gfx_SetFaceCulling(false); Gfx_SetFaceCulling(false);
} }
@ -150,51 +155,51 @@ static void MapRenderer_RenderTranslucentBatch(UInt32 batch) {
if (info->TranslucentParts == NULL) continue; if (info->TranslucentParts == NULL) continue;
ChunkPartInfo part = *(info->TranslucentParts + offset); ChunkPartInfo part = *(info->TranslucentParts + offset);
if (!part.HasVertices) continue; if (part.Offset < 0) continue;
MapRenderer_HasTranslucentParts[batch] = true; MapRenderer_HasTranslucentParts[batch] = true;
Gfx_BindVb(part.VbId); Gfx_BindVb(info->VbId);
bool drawXMin = (inTranslucent || info->DrawXMin) && part.XMinCount > 0; bool drawXMin = (inTranslucent || info->DrawXMin) && part.Counts[FACE_XMIN];
bool drawXMax = (inTranslucent || info->DrawXMax) && part.XMaxCount > 0; bool drawXMax = (inTranslucent || info->DrawXMax) && part.Counts[FACE_XMAX];
bool drawYMin = (inTranslucent || info->DrawYMin) && part.YMinCount > 0; bool drawYMin = (inTranslucent || info->DrawYMin) && part.Counts[FACE_YMIN];
bool drawYMax = (inTranslucent || info->DrawYMax) && part.YMaxCount > 0; bool drawYMax = (inTranslucent || info->DrawYMax) && part.Counts[FACE_YMAX];
bool drawZMin = (inTranslucent || info->DrawZMin) && part.ZMinCount > 0; bool drawZMin = (inTranslucent || info->DrawZMin) && part.Counts[FACE_ZMIN];
bool drawZMax = (inTranslucent || info->DrawZMax) && part.ZMaxCount > 0; bool drawZMax = (inTranslucent || info->DrawZMax) && part.Counts[FACE_ZMAX];
UInt32 offset = 0; Int32 offset = part.Offset;
if (drawXMin && drawXMax) { if (drawXMin && drawXMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMinCount + part.XMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX], offset);
Game_Vertices += (part.XMinCount + part.XMaxCount); Game_Vertices += (part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX]);
} else if (drawXMin) { } else if (drawXMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMIN], offset);
Game_Vertices += part.XMinCount; Game_Vertices += part.Counts[FACE_XMIN];
} else if (drawXMax) { } else if (drawXMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.XMaxCount, offset + part.XMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_XMAX], offset + part.Counts[FACE_XMIN]);
Game_Vertices += part.XMaxCount; Game_Vertices += part.Counts[FACE_XMAX];
} }
offset += part.XMinCount + part.XMaxCount; offset += part.Counts[FACE_XMIN] + part.Counts[FACE_XMAX];
if (drawZMin && drawZMax) { if (drawZMin && drawZMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMinCount + part.ZMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX], offset);
Game_Vertices += (part.ZMinCount + part.ZMaxCount); Game_Vertices += (part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX]);
} else if (drawZMin) { } else if (drawZMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMIN], offset);
Game_Vertices += part.ZMinCount; Game_Vertices += part.Counts[FACE_ZMIN];
} else if (drawZMax) { } else if (drawZMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.ZMaxCount, offset + part.ZMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_ZMAX], offset + part.Counts[FACE_ZMIN]);
Game_Vertices += part.ZMaxCount; Game_Vertices += part.Counts[FACE_ZMAX];
} }
offset += part.ZMinCount + part.ZMaxCount; offset += part.Counts[FACE_ZMIN] + part.Counts[FACE_ZMAX];
if (drawYMin && drawYMax) { if (drawYMin && drawYMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMinCount + part.YMaxCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMIN] + part.Counts[FACE_YMAX], offset);
Game_Vertices += (part.YMinCount + part.YMaxCount); Game_Vertices += (part.Counts[FACE_YMIN] + part.Counts[FACE_YMAX]);
} else if (drawYMin) { } else if (drawYMin) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMinCount, offset); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMIN], offset);
Game_Vertices += part.YMinCount; Game_Vertices += part.Counts[FACE_YMIN];
} else if (drawYMax) { } else if (drawYMax) {
Gfx_DrawIndexedVb_TrisT2fC4b(part.YMaxCount, offset + part.YMinCount); Gfx_DrawIndexedVb_TrisT2fC4b(part.Counts[FACE_YMAX], offset + part.Counts[FACE_YMIN]);
Game_Vertices += part.YMaxCount; Game_Vertices += part.Counts[FACE_YMAX];
} }
} }
} }