Penasaran Lubang Transparan Membuat Artefak


8

Jadi saya mencoba menerapkan medan "halus" di mesin blok saya dengan memberikan setiap blok permukaan suatu peta ketinggian.

Pada dasarnya, apa yang saya lakukan untuk menghasilkan "peta tinggi" ini untuk setiap blok adalah saya menghasilkan ketinggian pada interval 0,25 di sepanjang tepi blok. Kemudian, untuk membangun simpul blok, saya loop melalui ketinggian dan membuat segitiga dari tinggi ke tinggi dan meletakkan persegi panjang di bawah segitiga untuk membuat sesuatu seperti ini: masukkan deskripsi gambar di sini

Misalnya, untuk membangun sisi positif X blok, saya lakukan:

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

Saya tidak yakin apakah ini adalah kesalahan presisi floating point, tetapi ketika saya render, saya mendapatkan lubang-lubang aneh di perbatasan persegi panjang dasar (saya tahu itu lubang karena warnanya cocok dengan warna di belakangnya)

Apa yang benar-benar membuat saya marah adalah bahwa alih-alih seluruh baris, itu hanya titik-titik yang tampaknya acak.

masukkan deskripsi gambar di sini

Pandangan bingkai rangka dunia tidak mengungkapkan perbedaan. (semua itu adalah membuat game lag) masukkan deskripsi gambar di sini

Retas kecil cepat yang saya lakukan adalah untuk memperpanjang (i + 1) / 4 dalam kode ke (i + 1.01f) / 4, tapi saya lebih suka mendapatkan solusi konkret daripada sesuatu seperti itu.

Mungkin ada sesuatu di shader saya? Sampler tekstur saya adalah:

Texture TextureAtlas;
sampler TextureSampler = sampler_state
{
        texture = <TextureAtlas>;
    magfilter = POINT;
    minfilter = POINT;
    mipfilter = POINT;
    AddressU = WRAP;
    AddressV = WRAP;
};

Terima kasih sebelumnya!

Jawaban:


15

Dari diagram Anda, sepertinya geometri yang Anda bangun berisi persimpangan-T - tempat-tempat di mana sebuah simpul dari satu segitiga seharusnya terletak tepat di tepi segitiga yang lain (menghasilkan satu sisi bertemu dengan yang lain dalam bentuk "T"). Karena keterbatasan aritmatika presisi-terbatas, verteks biasanya tidak dapat dijamin untuk memenuhi tepian dengan sempurna dan Anda akan menemukan celah mikroskopis di antara mereka, yang sering muncul sebagai gangguan piksel tunggal karena satu piksel individu dapat mendarat di celah tersebut sementara tetangganya tidak.

Untuk memperbaikinya, Anda harus membangun geometri sedemikian rupa sehingga tidak ada persimpangan-T, dengan membelah setiap tepi tempat simpul seharusnya bertemu dengannya. Diagram ini menunjukkan contoh:

masukkan deskripsi gambar di sini

EDIT: Di atas berlaku untuk persimpangan-T secara umum. Untuk kasus spesifik Anda, seperti yang Ilmari Karonen tunjukkan dalam komentar, Anda dapat membuat geometri yang lebih baik seperti ini:

masukkan deskripsi gambar di sini

yang juga menghindari pertigaan dan memiliki lebih sedikit segitiga secara keseluruhan.


6
Cara yang lebih baik untuk menghindari pertigaan adalah dengan melakukan triangulasi seperti ini . Dengan begitu, Anda hanya perlu dua segitiga per segmen dan tidak ada simpul interior baru. (Anda bisa melakukannya dengan segitiga yang lebih sedikit, jika Anda mau; minimum adalah satu ditambah jumlah segmen.)
Ilmari Karonen

@IlmariKaronen Terima kasih, saya mengambil kebebasan untuk menambahkan diagram Anda ke jawabannya. :)
Nathan Reed
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.