Vâng, nói chung, một công cụ trò chơi sẽ có nhiều loại shader khác nhau. Mẫu điển hình là:
Trong khi khởi tạo công cụ và tải thế giới trò chơi, hãy chuẩn bị tất cả các shader bạn sẽ sử dụng để kết xuất. Bằng cách "chuẩn bị", tôi có nghĩa là tải chúng vào bộ nhớ, biên dịch chúng nếu cần và thực hiện tất cả các ID3D11Device::CreatePixelShader
lệnh gọi tương tự để có được các đối tượng đổ bóng D3D được phân bổ và sẵn sàng hoạt động. Giữ các đối tượng trong một mảng hoặc một số cấu trúc dữ liệu khác.
Thông thường, bạn sẽ có mối quan hệ một đối một giữa các trình tạo bóng đỉnh và trình tạo bóng pixel được thiết kế để hoạt động cùng nhau. Tôi nghĩ về chúng như một đối tượng duy nhất, mà tôi chỉ gọi là "shader", mặc dù nó thực sự chứa một shader đỉnh và một shader pixel (và có thể cả shader / hull / domain shader).
Mỗi khung hình, một khi bạn đã tìm thấy danh sách các đối tượng (mắt lưới) để kết xuất, hãy sắp xếp chúng theo shader. Ý tưởng là để giảm thiểu số lần bạn chuyển các shader trong một khung, bằng cách vẽ tất cả các đối tượng với một shader nhất định lại với nhau. Điều này là do chuyển đổi shaders là một hoạt động hơi đắt (mặc dù bạn chắc chắn có thể làm điều đó vài trăm hay một ngàn lần mỗi khung hình, vì vậy nó không thực sự là đắt tiền).
Trong thực tế, bạn có thể tiến thêm một bước và sắp xếp các mắt lưới bằng cách đổ bóng trước và vật liệu thứ hai. Theo "vật liệu", tôi có nghĩa là sự kết hợp của một shader và một tập hợp các kết cấu và tham số cho nó. Các shader thường có một số kết cấu và tham số số (được lưu trữ trong các bộ đệm không đổi) ăn vào chúng, vì vậy, ví dụ, một vật liệu gạch và vật liệu nhựa đường có thể sử dụng cùng một mã shader, chỉ với các kết cấu khác nhau.
Để vẽ, chỉ cần lặp qua các shader, đặt từng shader trong ID3D11DeviceContext
, đặt bất kỳ tham số nào (bộ đệm không đổi, kết cấu, v.v.), sau đó vẽ các đối tượng. Trong mã giả, bao gồm phân biệt shader / vật liệu tôi đã đề cập:
for each shader:
// Set the device context to use this shader
pContext->VSSetShader(shader.pVertexShader);
pContext->PSSetShader(shader.pPixelShader);
for each material that uses this shader:
// Set the device context to use any constant buffers, textures, samplers,
// etc. needed for this material
pContext->VSSetConstantBuffers(...);
pContext->PSSetConstantBuffers(...);
pContext->PSSetShaderResources(...);
pContext->PSSetSamplers(...);
for each mesh that uses this material:
// Set any constant buffers containing parameters specific to the mesh
// (e.g. world matrix)
pContext->VSSetConstantBuffers(...);
// Set the context to use the vertex & index buffers for this mesh
pContext->IASetInputLayout(mesh.pInputLayout);
pContext->IASetVertexBuffers(...);
pContext->IASetIndexBuffer(...);
pContext->IASetPrimitiveTopology(...)
// Draw it
pContext->DrawIndexed(...)
Có rất nhiều điều có thể nói về việc quản lý các đối tượng, mắt lưới, đổ bóng, bố cục đầu vào, bộ đệm liên tục, v.v. nhưng điều này là đủ để bạn bắt đầu. :)