Tò mò trong suốt Render Artifact


8

Vì vậy, tôi đang cố gắng thực hiện địa hình "trơn tru" trong công cụ khối của mình bằng cách cung cấp cho mỗi khối bề mặt một sơ đồ chiều cao.

Về cơ bản, những gì tôi làm để tạo ra các "chiều cao" cho mỗi khối là tôi tạo các độ cao trong các khoảng 0,25 dọc theo cạnh của khối. Sau đó, để xây dựng các đỉnh của khối, tôi lặp qua các độ cao và tạo các hình tam giác từ chiều cao đến chiều cao và đặt hình chữ nhật dưới các hình tam giác để tạo ra một cái gì đó như thế này: nhập mô tả hình ảnh ở đây

Ví dụ: để xây dựng mặt tích cực X của một khối, tôi làm:

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

Tôi không chắc đây có phải là lỗi chính xác của dấu phẩy động hay không, nhưng khi tôi kết xuất nó, tôi nhận được các lỗ tò mò này trên các đường viền của hình chữ nhật cơ sở (tôi biết chúng là các lỗ vì màu của chúng khớp với màu phía sau chúng)

Điều thực sự làm tôi thất vọng là thay vì cả một dòng, nó chỉ là những dấu chấm ngẫu nhiên.

nhập mô tả hình ảnh ở đây

Một cái nhìn khung dây của thế giới đã không tiết lộ bất kỳ sự khác biệt. (tất cả những gì nó đã làm là khiến trò chơi bị lag) nhập mô tả hình ảnh ở đây

Một cách nhanh chóng mà tôi đã làm là mở rộng (i + 1) / 4 trong mã thành (i + 1.01f) / 4, nhưng tôi muốn có một giải pháp cụ thể hơn là một giải pháp cụ thể.

Có lẽ đó là một cái gì đó trong shader của tôi? Bộ lấy mẫu kết cấu của tôi là:

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

Cảm ơn trước!

Câu trả lời:


15

Từ sơ đồ của bạn, có vẻ như hình học bạn đang xây dựng chứa các mối nối T - những nơi mà một đỉnh của một tam giác được cho là nằm chính xác trên cạnh của một tam giác khác (dẫn đến một cạnh gặp nhau theo hình chữ "T"). Do những hạn chế của số học chính xác hữu hạn, đỉnh thường không thể được đảm bảo để đáp ứng cạnh hoàn hảo và bạn sẽ tìm thấy các vết nứt siêu nhỏ giữa chúng, thường xuất hiện dưới dạng các pixel đơn lẻ vì một pixel riêng lẻ có thể rơi vào vết nứt trong khi hàng xóm của nó thì không.

Để khắc phục nó, bạn phải xây dựng hình học của mình theo cách không có mối nối T, bằng cách tách từng cạnh trong đó một đỉnh được cho là đáp ứng nó. Sơ đồ này cho thấy một ví dụ:

nhập mô tả hình ảnh ở đây

EDIT: Những điều trên áp dụng cho các mối nối T nói chung. Đối với trường hợp cụ thể của bạn, như Ilmari Karonen đã chỉ ra trong các bình luận, bạn có thể xây dựng hình học thậm chí tốt hơn như thế này:

nhập mô tả hình ảnh ở đây

trong đó cũng tránh các mối nối T và có tổng số tam giác ít hơn.


6
Một cách tốt hơn để tránh các mối nối T sẽ là thực hiện tam giác như thế này . Bằng cách đó, bạn chỉ cần hai hình tam giác trên mỗi đoạn và không có đỉnh bên trong mới. (Bạn có thể làm điều đó với số lượng hình tam giác thậm chí ít hơn, nếu bạn muốn; tối thiểu là một cộng với số lượng phân đoạn.)
Ilmari Karonen

@IlmariKaronen Cảm ơn, tôi đã tự do thêm sơ đồ của bạn vào câu trả lời. :)
Nathan Reed
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.