Quindi sto cercando di implementare un terreno "liscio" nel mio motore a blocchi dando ad ogni blocco di superficie una mappa di altezza.
Fondamentalmente, ciò che faccio per generare queste "mappe altimetriche" per ciascun blocco è generare le altezze a intervalli di 0,25 lungo il bordo del blocco. Quindi, per costruire i vertici del blocco, giro attraverso le altezze e creo triangoli da un'altezza all'altra e metto rettangoli sotto i triangoli per creare qualcosa del genere:
Ad esempio, per costruire il lato X positivo di un blocco, faccio:
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);
}
Non sono sicuro che si tratti di un errore di precisione in virgola mobile, ma quando lo rendering, ottengo questi curiosi fori sui bordi dei rettangoli di base (so che sono buchi perché i loro colori corrispondono al colore dietro di loro)
Quello che mi butta davvero fuori è che piuttosto che un'intera linea, sono solo punti apparentemente casuali.
Una visione del mondo wireframe non ha rivelato alcuna discrepanza. (tutto ciò che ha fatto è stato ritardare il gioco)
Un piccolo trucco che ho fatto è stato quello di estendere (i + 1) / 4 nel codice a (i + 1.01f) / 4, ma preferirei ottenere una soluzione concreta piuttosto che qualcosa del genere.
Forse è qualcosa nel mio shader? Il mio campionatore di texture è:
Texture TextureAtlas;
sampler TextureSampler = sampler_state
{
texture = <TextureAtlas>;
magfilter = POINT;
minfilter = POINT;
mipfilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
};
Grazie in anticipo!