J'essaie donc d'implémenter un terrain "lisse" dans mon moteur de blocs en donnant à chaque bloc de surface une hauteur.
Fondamentalement, ce que je fais pour générer ces "cartes de hauteur" pour chaque bloc, c'est que je génère les hauteurs à des intervalles de 0,25 le long du bord du bloc. Ensuite, pour construire les sommets du bloc, je boucle à travers les hauteurs et crée des triangles de hauteur en hauteur et place des rectangles sous les triangles pour créer quelque chose comme ceci:
Par exemple, pour construire le côté positif X d'un bloc, je fais:
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);
}
Je ne sais pas s'il s'agit d'une erreur de précision en virgule flottante, mais lorsque je la rends, j'obtiens ces curieux trous sur les bordures des rectangles de base (je sais que ce sont des trous parce que leurs couleurs correspondent à la couleur derrière elles)
Ce qui me dérange vraiment, c'est que plutôt que d'une ligne entière, ce sont juste des points apparemment aléatoires.
Une vision filaire du monde n'a révélé aucun écart. (il n'a fait que retarder le jeu)
Un petit hack rapide que j'ai fait a été d'étendre le (i + 1) / 4 dans le code à (i + 1.01f) / 4, mais je préfère obtenir une solution concrète que quelque chose comme ça.
C'est peut-être quelque chose dans mon shader? Mon échantillonneur de texture est:
Texture TextureAtlas;
sampler TextureSampler = sampler_state
{
texture = <TextureAtlas>;
magfilter = POINT;
minfilter = POINT;
mipfilter = POINT;
AddressU = WRAP;
AddressV = WRAP;
};
Merci d'avance!