Anti Aliasing được triển khai trong Ray Trace như thế nào?


12

Sau khi đọc một vài bài báo trực tuyến, tôi có thể tự tin nói rằng tôi không biết gì về cách Anti-Aliasing hoạt động khi Ray Trace .

Tất cả những gì tôi hiểu là A Pixel / Ray đơn được chia thành 4 pixel phụ và 4 tia chứ không phải 1 .

Ai đó có thể vui lòng giải thích làm thế nào được thực hiện (tốt nhất là với mã)?


2
Tôi có thể đề nghị bạn xem "supersampling" vi.wikipedia.org/wiki/Supersampling và có lẽ cũng là en.wikipedia.org/wiki/Distribution_ray_tracing ?
Simon F

2
Tôi cũng có thể khuyên bạn nên đọc chương này của PBRT pbrt.org/ch chương / pbrt_ch CHƯƠNG7.pdf và đọc bài viết này lgdv.cs.fau.de/get/785 (giải thích một kỹ thuật khác với kỹ thuật được triển khai trong pbrt).
Tom van Bussel

1
foreach pixel : p{acc = 0; foreach subsample : s { acc+=sample_scene(s);} store(p, acc);}
ratchet freak

Câu trả lời:


11

Tôi nghĩ thật an toàn khi nói rằng có hai cách khác nhau để thực hiện AA trong raytracing:

1: nếu bạn có hình ảnh cuối cùng và hình ảnh chiều sâu, có thể áp dụng hầu hết tất cả các kỹ thuật hiện có được sử dụng trong trò chơi (FXAA, v.v.) Những hình ảnh này hoạt động trực tiếp trên hình ảnh cuối cùng và không liên quan đến raytracing

2: phương pháp thứ hai là tính đến nhiều tia cho mỗi pixel và sau đó lấy trung bình kết quả. Đối với một phiên bản rất đơn giản, hãy nghĩ về nó như thế này:

  • trước tiên bạn hiển thị hình ảnh có kích thước 1024x1024, một tia cho mỗi pixel (ví dụ)
  • Sau khi kết xuất, bạn chia tỷ lệ hình ảnh thành 512x512 (mỗi 4 pixel được tính trung bình thành một) và bạn có thể nhận thấy rằng các cạnh mịn hơn. Bằng cách này, bạn đã sử dụng hiệu quả 4 tia cho mỗi pixel trong hình ảnh cuối cùng có kích thước 512x512.

Có các biến thể khác về phương pháp này. Ví dụ: bạn có thể điều chỉnh số lượng mẫu cho các pixel ở ngay cạnh của hình học có nghĩa là đối với một số pixel, bạn sẽ chỉ có 4 mẫu và cho các mẫu khác 16.

Kiểm tra các liên kết trong các ý kiến ​​trên.


Vì vậy, về cơ bản, tôi kết xuất một hình ảnh với kích thước lớn và khi lưu nó vào một hình ảnh, hạ thấp nó xuống kích thước thấp hơn? Điều đó có vẻ khá đơn giản :)! Đây có phải là phương pháp siêu mẫu?
Arjan Singh

1
@ Arjan Singh có nó là en.wikipedia.org/wiki/Supersampling , nhưng điều này là chậm nhất của tất cả, raytracing cho phép bạn dễ dàng làm SuperSampling thích nghi, có thể thực hiện tốt hơn rất nhiều
Raxvan

12

Raxvan hoàn toàn đúng khi các kỹ thuật khử răng cưa "truyền thống" sẽ hoạt động trong phương pháp raytracing, bao gồm cả những kỹ thuật sử dụng thông tin như độ sâu để khử răng cưa. Bạn thậm chí có thể thực hiện khử răng cưa tạm thời trong theo dõi tia.

Julien đã mở rộng trên mục thứ 2 của Raxvan, một lời giải thích về siêu mẫu, và cho thấy bạn thực sự làm điều đó như thế nào, cũng đề cập rằng bạn có thể chọn ngẫu nhiên vị trí của các mẫu trong pixel nhưng sau đó bạn đang vào quốc gia xử lý tín hiệu rất nhiều sâu hơn, và chắc chắn là như vậy!

NN

Nếu bạn làm điều đó, bạn vẫn có thể có được bí danh. Tốt hơn là KHÔNG làm điều đó, bởi vì bạn đang tăng tốc độ lấy mẫu của mình, do đó sẽ có thể xử lý dữ liệu tần số cao hơn (còn gọi là chi tiết nhỏ hơn), nhưng nó vẫn có thể gây ra răng cưa.

N

Khi bạn chỉ sử dụng các số ngẫu nhiên "thông thường" như bạn nhận được từ rand () hoặc std :: Uniform_int_distribution, được gọi là "nhiễu trắng" vì nó chứa tất cả các tần số, giống như cách ánh sáng trắng được tạo thành từ tất cả các màu khác (tần số ) của ánh sáng.

Sử dụng nhiễu trắng để tạo ngẫu nhiên các mẫu trong một pixel có vấn đề là đôi khi các mẫu của bạn sẽ co lại với nhau. Chẳng hạn, nếu bạn lấy trung bình 100 mẫu trong một pixel, nhưng tất cả chúng đều nằm ở góc trên bên trái của pixel, bạn sẽ không nhận được BẤT K information thông tin nào về các phần khác của pixel, do đó, màu pixel kết quả cuối cùng của bạn sẽ bị thiếu thông tin về màu sắc của nó.

Một cách tiếp cận tốt hơn là sử dụng một thứ gọi là nhiễu xanh chỉ chứa các thành phần tần số cao (như cách ánh sáng xanh là ánh sáng tần số cao).

Lợi ích của nhiễu xanh là bạn có được vùng phủ đều trên pixel, giống như bạn có được với lưới lấy mẫu thống nhất, nhưng, bạn vẫn nhận được một số ngẫu nhiên, biến bí danh thành nhiễu và cho bạn hình ảnh rõ hơn.

Thật không may, tiếng ồn màu xanh có thể rất tốn kém để tính toán, và các phương pháp tốt nhất dường như được cấp bằng sáng chế (cái quái gì vậy?!), Nhưng một cách để làm điều này, được phát minh bởi pixar (và tôi đã được cấp bằng sáng chế nhưng không chắc chắn 100%) là tạo một lưới chẵn các điểm mẫu, sau đó bù ngẫu nhiên mỗi điểm mẫu một lượng nhỏ - như một lượng ngẫu nhiên giữa cộng hoặc trừ một nửa chiều rộng và chiều cao của lưới lấy mẫu. Bằng cách này bạn có được một mẫu lấy mẫu tiếng ồn màu xanh với giá khá rẻ.

Lưu ý rằng đây là một hình thức lấy mẫu phân tầng và lấy mẫu đĩa poisson cũng là một dạng của đó, đây cũng là một cách tạo ra tiếng ồn màu xanh: https://www.jasondavies.com/poisson-disc/

Nếu bạn quan tâm đến việc đi sâu hơn có lẽ bạn cũng sẽ muốn kiểm tra câu hỏi và câu trả lời này!

Lý do cơ bản cho việc khử răng cưa bằng cách sử dụng nhiều mẫu ngẫu nhiên trong một pixel là gì?

Cuối cùng, công cụ này đang bắt đầu đi lạc vào vương quốc của dấu vết đường đi của monte carlo, đây là phương pháp phổ biến để thực hiện phương pháp raytracing quang. nếu bạn quan tâm đến việc tìm hiểu thêm về điều đó, hãy đọc nó!

http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/


7

Chúng ta hãy giả sử một vòng lặp chính raytracing khá điển hình:

struct Ray
{
    vec3 origin;
    vec3 direction;
};

RGBColor* image = CreateImageBuffer(width, height);

for (int j=0; j < height; ++i)
{
    for (int i=0; i < width; ++i)
    {
        float x = 2.0 * (float)i / (float)max(width, height) - 1.0;
        float y = 2.0 * (float)j / (float)max(width, height) - 1.0;

        vec3 dir = normalize(vec3(x, y, -tanHalfFov));
        Ray r = { cameraPosition, dir };

        image[width * j + i] = ComputeColor(r);
    }
}

Một sửa đổi có thể có của nó để làm 4 mẫu MSAA sẽ là:

float jitterMatrix[4 * 2] = {
    -1.0/4.0,  3.0/4.0,
     3.0/4.0,  1.0/3.0,
    -3.0/4.0, -1.0/4.0,
     1.0/4.0, -3.0/4.0,
};

for (int j=0; j < height; ++i)
{
    for (int i=0; i < width; ++i)
    {
        // Init the pixel to 100% black (no light).
        image[width * j + i] = RGBColor(0.0);

        // Accumulate light for N samples.
        for (int sample = 0; sample < 4; ++sample)
        {
            float x = 2.0 * (i + jitterMatrix[2*sample]) / (float)max(width, height) - 1.0;
            float y = 2.0 * (i + jitterMatrix[2*sample+1]) / (float)max(width, height) - 1.0;

            vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);
            Ray r = { cameraPosition, dir };

            image[width * j + i] += ComputeColor(r);
        }

        // Get the average.
        image[width * j + i] /= 4.0;
    }
}

Một khả năng khác là thực hiện một jitter ngẫu nhiên (thay vì ma trận dựa trên ma trận ở trên), nhưng sau đó bạn sẽ sớm bước vào lĩnh vực xử lý tín hiệu và phải đọc rất nhiều để biết cách chọn chức năng nhiễu tốt.

Mặc dù vậy, ý tưởng vẫn giống nhau: coi pixel là đại diện cho một khu vực hình vuông nhỏ và thay vì chỉ bắn một tia đi qua trung tâm của pixel, hãy bắn nhiều tia bao phủ toàn bộ vùng pixel. Phân bố tia càng dày đặc, tín hiệu bạn nhận được càng tốt.

PS: Tôi đã viết mã ở trên một cách nhanh chóng, vì vậy tôi mong đợi một vài lỗi trong đó. Nó chỉ có nghĩa là để hiển thị ý tưởng cơ bản.


Câu trả lời chính xác! Lợi ích của việc sử dụng phương pháp này trái ngược với phương pháp @Raxvan đã sử dụng là gì? Tôi sẽ nhận được kết quả tương tự bằng cách hiển thị kích thước lớn và sau đó thu nhỏ xuống kích thước nhỏ hơn?
Arjan Singh

Về cơ bản, với phương pháp dò tia, bạn không cần phải hiển thị hình ảnh lớn hơn sau đó thu nhỏ nó xuống. Điều đó có nghĩa là bạn linh hoạt hơn rất nhiều: bạn có thể có rất nhiều mẫu, bạn có thể thay đổi số lượng mẫu tùy theo khu vực và đơn giản, bạn không phải thêm bước bán lại.
Julien Guertault

2
Về chủ đề jitter, đây hóa ra là một chủ đề khá phức tạp. Đây là một bài viết tuyệt vời để phân tích hiện đại một vài năm trở lại đồ
họa.pixar.com / l Library / MultiJitteredSampling / apers.pdf

Mẫu mã ở trên sử dụng MSAA 4 mẫu, nếu tôi muốn làm 8 MSAA thì ma trận sẽ như thế nào? Tôi cần gì để thay đổi trong ma trận jitter hiển thị ở trên?
Arjan Singh
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.