Tất cả bài viết
Hướng dẫn · 8 min read

Tán lá dày đặc mà không phải trả hóa đơn frame rate: một hướng dẫn thực dụng

Cách lấp đầy một cảnh bằng thảm thực vật mà vẫn giữ nhanh: instancing, khoảng cách cull, chiến lược LOD, chi phí bóng đổ, overdraw, đặt mật độ, và vòng lặp profiling camera cố định chứng minh mỗi tối ưu thực sự đáng.

Illustration of a row of trees next to a rising frame-rate graph

Tóm lại: thảm thực vật dày đặc hiếm khi bị giết chỉ bởi số tam giác: nó chết bởi một ngàn draw call, overdraw từ các thẻ alpha bất cẩn, và bóng đổ mà không ai nhớ là còn bật. Hãy dồn công sức theo thứ tự này: instancing trước, khoảng cách cull thứ hai, bóng đổ thứ ba, LOD thứ tư, đặt mật độ thứ năm, và xác minh mỗi bước bằng cùng một camera cố định, một biến mỗi lần, nếu không bạn chẳng học được gì. Hướng dẫn này bao quát từng giai đoạn kèm chữ ký profiler cho bạn biết đó là vấn đề của bạn.

Tán rừng dày đặc phản chiếu trong một dòng suối tĩnh lặng Một khu rừng thật render "miễn phí" vì vật lý song song ồ ạt. GPU của bạn có thể giả lập cái nhìn đó ở 60 fps, nhưng chỉ khi bạn ngừng đánh bại bộ máy mà các engine đã cung cấp sẵn đúng cho công việc này.

Mô hình tư duy: năm nút thắt, một thứ tự

Hiệu năng thảm thực vật không phải một vấn đề, mà là năm, và chúng thống trị theo một trình tự có thể đoán. Draw call trói CPU trước; khoảng cách cull quyết định bạn thậm chí yêu cầu GPU vẽ bao nhiêu; bóng đổ lặng lẽ nhân đôi chi phí của mọi thứ đổ chúng; LOD và overdraw cai trị hóa đơn trên mỗi điểm ảnh; và đặt mật độ quyết định bạn thực sự cần bao nhiêu trong tất cả những cái đó. Tấn công chúng sai thứ tự và bạn sẽ tối ưu một thứ vốn không phải nút thắt. Thứ tự dưới đây là thứ tự mà chi phí thực sự cắn.

Instancing trước, mọi thứ khác sau

Một cây vẽ 5.000 lần rẻ hơn hẳn 5.000 cây riêng lẻ: cả hai engine đều batch các mesh lặp lại thành draw được instance, và việc đầu tiên của bạn chỉ đơn giản là đừng đánh bại bộ máy đó.

Unreal batch qua foliage và hierarchical instanced static meshes; Unity qua GPU instancing và chi tiết terrain. Cái lặng lẽ phá vỡ batch:

  • thảm thực vật đặt như các actor/đối tượng độc nhất thay vì instance;
  • biến thể vật liệu theo instance: dùng dữ liệu theo instance (màu, tỷ lệ) bên trong một vật liệu thay vì tạo một vật liệu cho mỗi cái nhìn;
  • đặt phân tán về mặt tổ chức khiến engine không thể cull các cụm theo đơn vị.

Dấu hiệu profiler rõ ràng: draw call tăng theo số cây. Nếu một tầm nhìn rừng cho thấy hàng ngàn draw call, sửa cái này trước khi chạm bất cứ thứ gì khác; không gì thấp hơn trong danh sách này cứu bạn được, vì bạn CPU-bound trước khi GPU thậm chí khởi động. Thảm thực vật được instance lành mạnh giữ draw call ở mức hàng trăm thấp cho cả một tầm nhìn rừng, bất kể có bao nhiêu ngàn cây trong đó.

Khoảng cách cull là tiền miễn phí

Cỏ không cần render ở 800 mét: đặt khoảng cách cull theo loại (lớp phủ mặt đất 30–60 m, bụi 100–200 m, chỉ cây mới xứng khoảng cách xa) với các dải fade để giấu sự bật.

Đây là thiết lập có giá trị-trên-phút cao nhất trong cả pipeline, và thường bị để ở "vô hạn" vì đó là mặc định và không ai để ý. Lý lẽ là tri giác: lớp phủ mặt đất chiếm chưa tới một điểm ảnh từ rất lâu trước 100 m; nó đóng góp đúng nghĩa không gì cho hình ảnh cuối trong khi vẫn tốn đỉnh, overdraw và công việc bóng đổ mỗi khung. Phủ xa thuộc về các hệ thống rẻ hơn: màu của vật liệu terrain, impostor mờ đục, hay đơn giản LOD xa của lớp terrain được sơn đúng màu xanh.

Các dải fade (dithered hoặc alpha) giấu sự bật ra để người chơi không bao giờ thấy chính khoảng cách cull. Chỉnh fade vừa đủ dài để vô hình và không hơn; một fade quá dài nghĩa là bạn đang trả cho hai biểu diễn của cùng một cây trong lúc crossfade.

Bóng đổ: nửa lặng lẽ của hóa đơn

TẮT đổ bóng động cho lớp phủ mặt đất nhỏ, giữ nó cho cây, và giới hạn theo khoảng cách cho bụi: bóng cỏ nhân đôi chi phí của bạn cho lợi ích thị giác gần bằng không.

Mỗi lá cỏ trong pass bóng đổ được vẽ lại, từ điểm nhìn của ánh sáng. Trong các cảnh dày đặc pass bóng đổ thường tốn bằng pass nền, nghĩa là bóng cỏ có thể là khoản mục lớn nhất trong cả ngân sách thảm thực vật trong khi về thị giác không thể phân biệt với một sự tối đi môi trường đơn giản ở gốc cụm. Cách sửa gần như miễn phí: tắt đổ bóng cho lớp phủ mặt đất, bật cho cây (bóng của chúng làm công việc bố cục thật), giới hạn khoảng cách cho phần ở giữa. Rồi kiểm pass bóng đổ trong profiler trước và sau: thường là chiến thắng đơn lớn nhất sau instancing, và mất vài phút.

LOD: ngân sách cho hình bóng, không phải đa giác

Một chuỗi LOD thảm thực vật tốt giữ đường viền và chém phần bên trong: xác minh khoảng cách chuyển bằng mắt, và tối ưu mạnh nhất mesh LOD cuối trước impostor, vì đó là cái trên màn hình trong mọi cảnh rộng.

Dương xỉ và bụi thấp trên nền rừng dọc một lối mòn Cây tầng mặt đất như thế này là nơi các thiết lập khoảng cách cull và bóng đổ đáng nhất: hàng ngàn instance, mỗi cái đóng góp gần bằng không quá vài chục mét, mỗi cái nhân đôi chi phí nếu đổ một bóng động.

Một chuỗi thực dụng cho cây hero: mesh đầy đủ → giảm phần trong ~50 % (cùng hình bóng) → ~15 % với thẻ hợp nhất → impostor/billboard mờ đục. Hai lưu ý tiết kiệm nỗi đau thật:

  • Ngay cả trong engine có hình học ảo hóa, impostor ở xa vẫn đáng, vì overdraw và bóng đổ vẫn là chi phí thật bất kể tam giác được trả thế nào. Hình học ảo hóa giải quyết số tam giác, không phải chi phí trong suốt.
  • Trong suốt là kẻ thù ở khoảng cách. Các thẻ alpha-tested dày chồng overdraw đúng nơi GPU yếu nhất: các LOD giữa. Ưu tiên lá mesh ở gần và impostor mờ đục ở xa; phần giữa nặng alpha là nơi thời gian khung ẩn mình. Nếu một LOD đắt bí ẩn, nó gần như luôn là cái trong suốt.

Overdraw: chi phí bạn không thể thấy

Overdraw là GPU tô cùng một điểm ảnh nhiều lần qua các bề mặt trong suốt chồng lên nhau, lời nguyền đặc thù của thảm thực vật, vô hình trong hình ảnh cuối, và thường là lý do một cảnh "nhẹ" lại chậm.

Hầu hết engine có chế độ hiển thị overdraw; bật nó và nhìn một cánh đồng cỏ. Nếu nó phát sáng trắng, bạn đang tô mỗi điểm ảnh năm hay mười lần khi các thẻ alpha chồng lấn chất đống. Giảm nhẹ: ít hơn, lá to hơn thay vì nhiều lá mỏng; hình học mờ đục nơi hình bóng cho phép; và cull mạnh tay các thẻ đóng góp ít nhất. Overdraw là thủ phạm kinh điển của "cảnh của tôi chậm nhưng chẳng có gì trông đắt", vì tam giác thì rẻ mà điểm ảnh bị trả nhiều lần.

Mật độ là một quyết định thiết kế, không phải vị trí thanh trượt

Dày nơi người chơi đi và nhìn, thưa nơi họ không: một dải 20 m chi tiết phong phú dọc lối đi đọc lên "tươi tốt khắp nơi" với một phần chi phí đồng đều.

Mask độ dốc và độ cao làm một phần điều này tự động (mặt dốc và cao nguyên xa không cần lớp phủ mặt đất chút nào), và gom cụm làm phần còn lại: các cụm có khoảng trống render rẻ hơn lấp đầy đồng đều trông tự nhiên hơn, nên chiến thắng hiệu năng và chiến thắng cái đẹp chỉ cùng một hướng. Đây là nơi công cụ đặt kiếm cơm: vẽ mật độ bằng mask và luật theo loài, rồi nướng thẳng thành instance gốc của engine, là sự khác biệt giữa một buổi chiều và một tuần. Đó là cốt lõi của việc scatter của Numivo làm, và vì nó nướng thành foliage thường và mesh được instance, mọi kỹ thuật trong bài này áp dụng không đổi cho kết quả. Không có runtime plugin giữa bạn và các tối ưu chuẩn; cảnh đã nướng chỉ là nội dung engine.

Vòng lặp profiling

Cùng camera, cùng tầm nhìn, một biến mỗi lần: đo thời gian khung GPU, draw call, pass bóng đổ và overdraw sau mỗi thay đổi.

Chọn một "camera ngân sách" cố định ở tầm nhìn dày nhất và chụp thống kê trước và sau mỗi bước ở trên. Kỷ luật quan trọng vì các tối ưu thảm thực vật tương tác: một thay đổi khoảng cách cull thay đổi số instance mà pass bóng đổ thấy; một thay đổi LOD thay đổi overdraw; một thay đổi mật độ thay đổi tất cả cùng lúc. Bay dạo ngẫu nhiên tạo ra số ngẫu nhiên và những tranh luận không thể phản nghiệm về việc một thay đổi có giúp không. Camera cố định tạo ra các quyết định bạn có thể bảo vệ. Giữ số liệu trong một bảng chung và đường xu hướng kể cho bạn câu chuyện mà một phép đo đơn không thể.

Con số thực địa đáng ăn cắp

  • Cull lớp phủ mặt đất: 30–60 m · bụi: 100–200 m · cây: đường ngắm
  • Draw call cho một tầm nhìn rừng được instance lành mạnh: hàng trăm thấp
  • Tỷ trọng pass bóng đổ trong cảnh dày đặc: thường ~một nửa chi phí thảm thực vật, tắt bóng cỏ là chiến thắng lớn rẻ nhất từng có
  • Chiều rộng dải dressing lối đi đọc lên "tươi tốt khắp nơi": ~20 m
  • Số LOD cho một cây hero: 3 mesh LOD + impostor mờ đục
  • Mục tiêu overdraw cho cỏ: dưới ~3× trong chế độ xem overdraw, không phải 8–10× trắng phát sáng của các thẻ alpha chồng chất

Mini-FAQ

Nanite / hình học ảo hóa có làm điều này lỗi thời không? Nó thay đổi dòng nào thống trị, không phải kỷ luật. Overdraw từ thẻ alpha, chi phí bóng đổ và chi phí chung theo instance đều còn, và impostor ở xa vẫn đáng. Đo trên phần cứng mục tiêu thay vì cho rằng công nghệ mới đã giải quyết nút thắt cụ thể của bạn: nó có thể đã dời nó, không phải bỏ nó.

Sao cảnh của tôi chậm ngay cả ở mật độ thấp? Những nghi phạm thường gặp, theo thứ tự: cỏ đổ bóng động, vật liệu độc nhất theo biến thể đánh bại batch, khoảng cách cull ở vô hạn, hay một chuỗi LOD alpha-tested chồng overdraw. Mỗi cái có một chữ ký profiler riêng, nên kiểm trước khi đổi, kẻo bạn sửa nhầm cái.

Dày bao nhiêu là "quá dày" cho lối chơi? Tính dễ đọc khi chiến đấu giới hạn mật độ trước cả hiệu năng: nếu các hình bóng biến mất vào sự bừa bộn, người chơi trách game, không trách dressing. Dày ở tầm nhìn, vừa phải ở đấu trường là khuôn mẫu sống sót cả profiler lẫn playtest.

Nên nướng hay giữ theo thủ tục? Nướng để phát hành, vì instance đã nướng profile trung thực và phát hành không phụ thuộc runtime. Giữ thiết lập theo thủ tục (mask, luật, seed) trong quản lý phiên bản để bạn có thể nướng lại sau một thay đổi terrain mà không làm lại bằng tay.

Trông dày nhanh không phải là mâu thuẫn: nó chủ yếu là kỷ luật làm năm việc đúng thứ tự và chứng minh mỗi cái bằng cùng một camera.