- vừa được xem lúc

Rendering Path trong Unity: Deferred Shading hay Forward Rendering?

0 0 7

Người đăng: Phuong Le

Theo Viblo Asia

Phuongne, Th3 11, 2020


Lighting

Người xưa cho rằng “Lights are expensive”, điều này đúng, và chính điều này tạo nên sự khác biệt giữa các loại Rendering Path trong Unity, thông thường Deferred Shading sẽ hỗ trợ những dòng máy cấu hình cao như high-end pc, và Foward Rendering sẽ hỗ trợ mobile tốt hơn

“Vậy tại sao lại dựa vào lightings để phân biệt 2 phương pháp render này?”

Trong Unity, một light sẽ render các objects theo 3 kiểu: per-pixel (từng pixel một), per-vertex (từng vertex một) và Spherical Harmonics (SH), theo đó, per-pixel light ngốn performance nhất, tiếp đó là per-vertex,…

per-pixel (trái) và per-vertex (phải)

Ở 2 khối low-poly trên, per-pixel làm khá tốt phần ánh sáng khi chỉ có rất ít đỉnh, trong khi per-vertex ánh sáng lại có vẻ thô hơn. Trong per-vertex lighting, mỗi vertex sẽ được tính toán một cách riêng biệt, sau đó các pixels ở giữa các vertices sẽ được tính toán phối màu theo thuật toán,

Về per-pixel lighting, mỗi pixel lại được tính toán riêng biệt mà số lượng pixels lớn hơn rất nhiều so với vertices nên rõ ràng rằng mức độ chi tiết cũng như sự phức tạp cao hơn, tiêu tốn tài nguyên hơn per-vertice.

Điều này tạo nên sự khác biệt giữa Deferred Shading rendering và Forward rendering, vào tab Graphics của Project Settings để chọn.

Foward và Deferred Shading

(Vì mình không thường xuyên làm việc với deferred shading nên bài viết sẽ tập trung hơn vào Forward rendering)

Rendering Paths này nằm trong phần 2, Rendering Objects của quy trình Render trong Unity, mình có nói sơ qua trong bài Render Pipeline trong Unity

Deferred Shading Rendering

Ưu điểm

Deferred Shading rendering cho phép vẽ không giới hạn số lượng lights và đặc biệt là per-pixel lights mà vẫn giữ performance ở một giới hạn hợp lý, trong khi nếu sử dụng nhiều lights ở Forward rendering lại tăng số lượng draw call -> giảm graphics performance.

Sử dụng per-pixel lightings, graphics nhìn rất fancy và đẹp mắt.

Ở Deferred Shading, số lượng DrawCall không phụ thuộc vào số lượng lights mà phụ thuộc vào số lượng objects, objects càng nhiều Draw Call càng tăng. Trong khi đó số lượng DrawCall ở Foward Rendering lại phụ thuộc vào cả số lượng lights và số lượng objects, đồng nghĩa thêm một lights sẽ x2 DrawCall cho Objets (chưa tính Shadows, Skybox,…)

(xem ví dụ ở nguồn bài viết – source: catlikecoding)

Nhược điểm

  • Deferred Shading không hỗ trợ anti-aliasing (khử răng cưa).
  • Không xử lý các vật thể bán trong suốt (alpha < 1) hay semi-transparent GameObjects.
  • Không hỗ trợ flag (cờ) Receive Shadows ở component MeshRenderer.
  • Giới hạn hỗ trợ về culling masks.
  • Ngốn performance nên không sử dụng trên các thiết bị low-end hay mobiles.

Yêu cầu

Các object với shaders không hỗ trợ Deferred shading sẽ sử dụng Forward rendering.

Theo Unity Documents, Deferred Shading yêu cầu card đồ họa có chức năng Multiple Render Targets (MRT) – một chức năng vẽ nhiều images cùng một lúc theo hình minh họa bên dưới. Yêu cầu về Shader Model 3.0 hoặc cao hơn, hỗ trợ vẽ depth texture run-time.

Diffuse color, normal, và depth của các objects (từ trái sang phải)

Kết quả cuối cùng

Thông thường, các card đồ họa máy tính cách đây 10-15 năm cũng đã hỗ trợ các chức năng này.
Còn về mobile devices, “chỉ yêu cầu thiết bị chạy OpenGL ES 3.0“, tuy nhiên best practice hiện nay vẫn là tuyệt đối không sử dụng deferred shading trên các mobile games.

Foward Rendering

Foward Rendering khá là quen thuộc đối với các bạn lập trình game mobile (mình) và mặc định built-in rendering path khi tạo một project trên Unity cũng là Foward Rendering

Vì ưu điểm của forward rendering path phần lớn là nhược điểm của deferred shading nên ta không nhắc lại mục này nữa

Khuyết điểm

  • Tăng Draw Call nhanh hơn khi sử dụng nhiều lightings
  • Graphics không được hoa mỹ và realistic như Deferred Shading

Các Lights trong Forward Rendering

Như đã giới thiệu ở trên, lights trong forward rendering chia làm các loại bao gồm: ver-pixel light, ver-vertex light và spherical harmonics (SH) light, trong đó SH light là light có performance tốt nhất.

Trong Forward Rendering, một vài lights sáng nhất sẽ được mặc định đặt là ver-pixel light, cho phép tối đa 4 point lights chiếu sáng theo kiểu per-vertex, các lights còn lại được tính theo Spherical Harmonics (SH).

Đây là một ví dụ mình trích ra từ Unity3D Documents:

Ví dụ 8 lights -1 objects

Bối cảnh: tất cả các lights đều có cùng color (màu), intensity (độ sáng), Render Mode là Auto, Pixel Light Count trong Quality là 4.
Theo lý thuyết, các lights sáng nhất sẽ tính toán và render object trên ví dụ theo per-pixel, cho phép tối đa 4 per-vertex lights, số còn lại lại sẽ là SH lights.
Như vậy, A -> D là 4 lights sáng nhất nên sẽ render object trên theo per-pixel, 4 lights tiếp theo (D -> G) sẽ là per-vertex light, còn lại 2 lights G và H là SH lights

“Tại sao 4 lights sáng nhất lại là per-pixel light mà không phải 1 2 3… lights sáng nhất?”

Trong phần bối cảnh mình có đề cập tới Pixel Light Count trong Quality tab (Edit -> Project Setting -> Quality) bằng 4, như vậy sẽ lấy tối đa 4 per-pixel lights

“Chỗ chỉnh sửa Render Mode cho các lights này ở đâu vậy?”

Chúng ta vào component Light xem phần Render Mode, có 3 cờ (flags): Important, Not Important và Auto:

  • Not Important: Light với setting này sẽ thuộc loại per-vertex hoặc SH.
  • Important: render theo per-pixel.
  • Auto: đây là cờ mặc định của Light component, Light sẽ được xác định theo độ ưu tiên về độ sáng (brightness) và khoảng cách (distance) tới object.

“Nếu ở ví dụ ban nãy Render Mode không phải là Auto mà là Important hoặc Not Important thì sao?”

Vì mình không thấy nhiều tài liệu nên đã làm một vài thử nghiệm trên phiên bản 2019.3.0f6:
Các Lights có renderMode là Important và Not Important không phụ thuộc vào thuộc tính Pixel Light Count Count (PLC) trong Quality tab mà ngược lại

  • Important-light luôn là per-pixel light và Not-important-light luôn là per-vertex (hoặc SH) light bất kể PLC = 0 hay = n.
  • Mặc dù Important (hoặc Not-important) light không bị ảnh hưởng bởi PLC nhưng PLC lại bị ảnh hưởng bởi 2 kiểu lights đó

Ví dụ có 3 important lights và PLC = từ 0 -> 3 thì các auto-light (renderMode = Auto) còn lại đều không phải là per-pixel.

Claims

Bài viết được đăng vào 2020, chỉ có giá trị tham khảo các bạn nhé 😉

Lời kết và nguồn tham khảo

https://blog.theknightsofunity.com/forward-vs-deferred-rendering-paths/
https://catlikecoding.com/unity/tutorials/rendering/part-13/
https://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html
https://docs.unity3d.com/Manual/RenderTech-DeferredShading.html

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tạo setting game trên inspector.

. Chào các bạn,. Hôm nay chúng ta sẽ cùng tạo 1 setting/config cho game trên inspector nhé. Câu trả lời đó là khi chúng ta cần 1 cái gì đó để thao tác trong editor, trực quan nhất, không cần sửa code để cập nhật dữ liệu.... Và hẳn các bạn cũng từng làm việc với những value trên inspector rồi, ví dụ

0 0 17

- vừa được xem lúc

Hướng dẫn đưa nhân vật từ Mixamo vào demo.

. Chào các bạn. Bài này chúng ta chỉ tìm hiểu cách để lấy model, animation về, setting sao cho nó chạy được trong Unity để làm demo là ngon rồi nhé . Bước 1: Đăng nhập. Hãy tạo tài khoản nếu các bạn chưa có.

0 0 21

- vừa được xem lúc

Cơ bản về Rigidbody trong Unity3D

Phuong Le at 31-10-2019 - phuongne. Bài viết từ 2019 nên chỉ có giá trị tham khảo bạn nhé . . Rigidbody là gì.

0 0 13

- vừa được xem lúc

Một số folder đặc biệt trong Unity

Phuong Le 2019 - phuongne. Bài viết từ 2019 nên chỉ có giá trị tham khảo bạn nhé .

0 0 10

- vừa được xem lúc

Coroutine trong Unity là gì? Có liên quan tới Threads hay không?

Phuongne, Th11 17, 2019. Sơ qua một chút về Coroutine và StartCoroutine(.

0 0 8

- vừa được xem lúc

So sánh nhẹ Coroutine và Invoke

Phuongne - 31-10-2019. . Roài, đây sẽ là một bài viết ngắn nên mình đi vào chi tiết luôn, khởi mở đầu giới thiệu dài dòng nhá anh em. Coroutine với Invoke là gì.

0 0 10