Ich versuche also, "glattes" Gelände in meine Block-Engine zu implementieren, indem ich jedem Oberflächenblock eine Höhenkarte gebe.
Grundsätzlich generiere ich diese "Höhenkarten" für jeden Block, indem ich die Höhen in Intervallen von 0,25 entlang der Blockkante generiere. Um dann die Eckpunkte des Blocks zu bilden, durchlaufe ich die Höhen und erstelle Dreiecke von Höhe zu Höhe und lege Rechtecke unter die Dreiecke, um so etwas zu erstellen:
Um beispielsweise die X-positive Seite eines Blocks zu erstellen, gehe ich wie folgt vor:
Vector2[] uv = BlockUtil.UVMappings[(byte)side]; // uv[0] = top left
float height;
float nextHeight;
float min;
float tex_len = 1f / EngineGlobals.TEXTURE_ATLAS_SIDE;
for (int i = 0; i < 4; i++)
{
height = (float)b.Heights[4, i] / 255f;
nextHeight = (float)b.Heights[4, i + 1] / 255f;
min = Math.Min(height, nextHeight);
//create the triangles at the top
if (nextHeight > height)
{
int offset = ch.vertexMap.Count;
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * (i / 4f), (1-height)*tex_len), blockPos, new Vector3(1f, height, i / 4f), tr, isliquid);
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * ((i + 1) / 4f), 0), blockPos, new Vector3(1f, height, (i + 1) / 4f), tr, isliquid);
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * ((i + 1) / 4f), 0), blockPos, new Vector3(1f, nextHeight, (i + 1) / 4f), tr, isliquid);
AddTriIndices(offset, 0, 1, 2);
}
else if (nextHeight < height)
{
int offset = ch.vertexMap.Count;
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * (i / 4f), (1-height)*tex_len), blockPos, new Vector3(1f, height, i / 4f), tr, isliquid);
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * (i / 4f), (1-nextHeight)*tex_len), blockPos, new Vector3(1f, nextHeight, i / 4f), tr, isliquid);
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * ((i + 1) / 4f), (1 - nextHeight) * tex_len), blockPos, new Vector3(1f, nextHeight, (i + 1) / 4f), tr, isliquid);
AddTriIndices(offset, 0, 1, 2);
}
// else: heights are equal; ignore
// create the base rectangle
AddVertex(ch, 0, 0, uv[0] + new Vector2(tex_len * (float)i / 4f + tex_len / 4f, (1 - min) * tex_len), blockPos, new Vector3(1, min, (float)(i + 1) / 4f), tr, isliquid);
AddVertex(ch, 0, 1, uv[0] + new Vector2(tex_len * (float)i/4f, (1 - min) * tex_len), blockPos, new Vector3(1, min, (float)i / 4f), tr, isliquid);
AddVertex(ch, 0, 2, uv[0] + new Vector2(tex_len * (float)i / 4f + tex_len / 4f, tex_len), blockPos, new Vector3(1, 0, (float)(i + 1) / 4f), tr, isliquid);
AddVertex(ch, 0, 3, uv[0] + new Vector2(tex_len * (float)i / 4f, tex_len), blockPos, new Vector3(1, 0, (float)i / 4f), tr, isliquid);
AddIndices(ch, 0, 1, 2, 2, 1, 3, isliquid);
}
Ich bin nicht sicher, ob dies ein Gleitkommapräzisionsfehler ist, aber wenn ich ihn rendere, erhalte ich diese merkwürdigen Löcher an den Rändern der Basisrechtecke (ich weiß, dass sie Löcher sind, weil ihre Farben mit der Farbe dahinter übereinstimmen).
Was mich wirklich abschreckt, ist, dass es sich nicht um eine ganze Zeile, sondern nur um scheinbar zufällige Punkte handelt.
Eine Drahtgitteransicht der Welt ergab keine Unstimmigkeiten. (Alles was es getan hat war das Spiel zu verzögern)
Ein kurzer kleiner Hack, den ich gemacht habe, war, das (i + 1) / 4 im Code auf (i + 1.01f) / 4 zu erweitern, aber ich würde lieber eine konkrete Lösung als so etwas bekommen.
Vielleicht ist es etwas in meinem Shader? Mein Textur-Sampler ist:
Texture TextureAtlas;
sampler TextureSampler = sampler_state
{
texture = <TextureAtlas>;
magfilter = POINT;
minfilter = POINT;
mipfilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
};
Danke im Voraus!