Nhìn chung có hai phương pháp để đối phó với điều này. Ngày nay, chúng được gọi là kết xuất chuyển tiếp và kết xuất hoãn lại. Có một biến thể trên hai cái này mà tôi sẽ thảo luận dưới đây.
Chuyển tiếp kết xuất
Kết xuất mỗi đối tượng một lần cho mỗi ánh sáng ảnh hưởng đến nó. Điều này bao gồm ánh sáng xung quanh. Bạn sử dụng chế độ hòa trộn phụ gia ( glBlendFunc(GL_ONE, GL_ONE)
), để mỗi đóng góp của ánh sáng được thêm vào nhau. Vì sự đóng góp của các loại đèn khác nhau là phụ gia, bộ đệm khung cuối cùng có giá trị
Bạn có thể nhận được HDR bằng cách kết xuất với bộ đệm khung hình nổi. Sau đó, bạn vượt qua cảnh cuối cùng để giảm các giá trị ánh sáng HDR xuống phạm vi có thể nhìn thấy; đây cũng sẽ là nơi bạn thực hiện nở hoa và các hiệu ứng hậu kỳ khác.
Một cải tiến hiệu suất phổ biến cho kỹ thuật này (nếu cảnh có nhiều đối tượng) là sử dụng "pre-pass", trong đó bạn kết xuất tất cả các đối tượng mà không vẽ bất kỳ thứ gì cho bộ đệm khung màu (sử dụng glColorMask
để tắt ghi màu). Điều này chỉ lấp đầy trong bộ đệm sâu. Bằng cách này, nếu bạn kết xuất một vật thể phía sau vật thể khác, GPU có thể nhanh chóng bỏ qua những mảnh vỡ đó. Nó vẫn phải chạy shader đỉnh, nhưng nó có thể bỏ qua các tính toán shader mảnh đắt tiền hơn.
Điều này là đơn giản để mã và dễ hình dung hơn. Và trên một số phần cứng (chủ yếu là GPU di động và GPU nhúng), nó có thể hiệu quả hơn so với giải pháp thay thế. Nhưng trên phần cứng cao cấp hơn, sự thay thế thường thắng trong các cảnh có nhiều ánh sáng.
Trì hoãn kết xuất
Kết xuất hoãn lại phức tạp hơn một chút.
Phương trình chiếu sáng bạn sử dụng để tính toán ánh sáng cho một điểm trên một bề mặt sử dụng các tham số bề mặt sau:
- Vị trí bề mặt
- Bề mặt chuẩn
- Bề mặt khuếch tán màu
- Màu sắc bề mặt
- Bề mặt sáng bóng
- Có thể các tham số bề mặt khác (tùy thuộc vào mức độ phức tạp của phương trình chiếu sáng của bạn)
Trong kết xuất về phía trước, các tham số này có được chức năng chiếu sáng của mảnh vỡ bằng cách được truyền trực tiếp từ trình tạo bóng đỉnh, được kéo từ kết cấu (thường thông qua tọa độ kết cấu được truyền từ trình tạo bóng đỉnh) hoặc được tạo từ toàn bộ vải trong trình tạo bóng mảnh các thông số khác. Màu khuếch tán có thể được tính bằng cách kết hợp màu trên mỗi đỉnh với kết cấu, kết hợp nhiều họa tiết, bất cứ thứ gì.
Trong kết xuất hoãn lại, chúng tôi thực hiện tất cả điều này rõ ràng. Trong lần đầu tiên, chúng ta kết xuất tất cả các đối tượng. Nhưng chúng ta không thể hiện màu sắc . Thay vào đó, chúng tôi đưa ra các tham số bề mặt . Vì vậy, mỗi pixel trên màn hình có một bộ thông số bề mặt. Điều này được thực hiện thông qua kết xuất với kết cấu ngoài màn hình. Một kết cấu sẽ lưu trữ màu khuếch tán dưới dạng RGB của nó và có thể là độ sáng bóng đặc trưng như alpha. Một kết cấu khác sẽ lưu trữ màu sắc đặc biệt. Một phần ba sẽ lưu trữ bình thường. Và như vậy.
Các vị trí thường không được lưu trữ. Thay vào đó, nó được hoàn nguyên trong lần thứ hai bởi toán học quá phức tạp để vào đây. Có thể nói, chúng tôi sử dụng bộ đệm độ sâu và vị trí phân đoạn không gian màn hình làm đầu vào để tìm ra vị trí không gian camera của điểm trên một bề mặt.
Vì vậy, bây giờ khi các kết cấu này chủ yếu chứa tất cả thông tin bề mặt cho mỗi pixel hiển thị trong cảnh, chúng tôi bắt đầu hiển thị các hình tứ giác toàn màn hình. Mỗi ánh sáng được hiển thị toàn màn hình quad. Chúng tôi lấy mẫu từ kết cấu tham số bề mặt (và khôi phục vị trí), sau đó chỉ cần sử dụng chúng để tính toán sự đóng góp của ánh sáng đó. Điều này được thêm (một lần nữa glBlendFunc(GL_ONE, GL_ONE)
) vào hình ảnh. Chúng tôi tiếp tục làm điều này cho đến khi chúng tôi hết đèn.
HDR một lần nữa là một bước hậu xử lý.
Nhược điểm lớn nhất của kết xuất hoãn lại là khử răng cưa. Nó đòi hỏi một chút công việc để antialias đúng cách.
Ưu điểm lớn nhất, nếu GPU của bạn có nhiều băng thông bộ nhớ, là hiệu năng. Chúng tôi chỉ hiển thị hình học thực tế một lần (hoặc 1 + 1 cho mỗi ánh sáng có bóng, nếu chúng tôi đang thực hiện ánh xạ bóng). Chúng tôi không bao giờ dành bất kỳ thời gian nào cho các pixel hoặc hình học ẩn không thể nhìn thấy sau này. Tất cả thời gian vượt qua ánh sáng được dành cho những thứ thực sự có thể nhìn thấy.
Nếu GPU của bạn không có nhiều băng thông bộ nhớ, thì vượt qua ánh sáng thực sự có thể bắt đầu bị tổn thương. Kéo từ 3-5 họa tiết trên mỗi pixel màn hình không thú vị.
Vượt qua nhẹ
Đây là một loại biến thể của kết xuất hoãn lại có sự đánh đổi thú vị.
Giống như trong kết xuất hoãn lại, bạn kết xuất các tham số bề mặt của mình thành một bộ đệm. Tuy nhiên, bạn đã viết tắt dữ liệu bề mặt; dữ liệu bề mặt duy nhất bạn quan tâm trong thời gian này là giá trị bộ đệm độ sâu (để tái tạo lại vị trí), bình thường và độ sáng bóng đặc trưng.
Sau đó, với mỗi ánh sáng, bạn chỉ tính kết quả chiếu sáng. Không nhân với màu bề mặt, không có gì. Chỉ là dấu chấm (N, L) và thuật ngữ cụ thể, hoàn toàn không có màu sắc bề mặt. Các thuật ngữ cụ thể và khuếch tán nên được giữ trong các bộ đệm riêng biệt. Các thuật ngữ cụ thể và khuếch tán cho mỗi ánh sáng được tóm tắt trong hai bộ đệm.
Sau đó, bạn kết xuất lại hình học, sử dụng tổng số tính toán ánh sáng cụ thể và khuếch tán để thực hiện kết hợp cuối cùng với màu bề mặt, do đó tạo ra độ phản xạ tổng thể.
Ưu điểm ở đây là bạn có được nhiều mẫu trở lại (ít nhất, dễ dàng hơn so với trả chậm). Bạn thực hiện kết xuất theo từng đối tượng ít hơn kết xuất phía trước. Nhưng điều chính yếu hơn là việc cung cấp này là thời gian dễ dàng hơn để có các phương trình chiếu sáng khác nhau cho các bề mặt khác nhau.
Với kết xuất hoãn lại, bạn thường vẽ toàn bộ cảnh với cùng một bóng đổ trên mỗi ánh sáng. Vì vậy, mọi đối tượng phải sử dụng các tham số vật liệu giống nhau. Với ánh sáng trước, bạn có thể cung cấp cho mỗi đối tượng một bóng đổ khác nhau, để nó có thể tự thực hiện bước chiếu sáng cuối cùng.
Điều này không cung cấp nhiều tự do như trường hợp kết xuất phía trước. Nhưng nó vẫn nhanh hơn nếu bạn có băng thông kết cấu dự phòng.