Ya, mesin game pada umumnya akan memiliki beragam shader yang berbeda. Pola khasnya adalah:
Saat menginisialisasi mesin dan memuat dunia game, siapkan semua shader yang akan Anda gunakan untuk rendering. Dengan "mempersiapkan" maksud saya memuatnya ke dalam memori, kompilasi jika perlu, dan lakukan semua ID3D11Device::CreatePixelShader
panggilan serupa untuk mendapatkan objek shader D3D yang dialokasikan dan siap untuk digunakan. Simpan objek dalam array atau struktur data lainnya.
Biasanya Anda akan memiliki hubungan satu-ke-satu antara vertex shaders dan pixel shaders yang dirancang untuk bekerja bersama. Saya menganggap mereka sebagai objek tunggal, yang saya sebut "shader", meskipun itu benar-benar berisi shader vertex dan pixel shader (dan mungkin juga geometri / lambung / domain shader juga).
Setiap bingkai, setelah Anda menemukan daftar objek (jerat) untuk diurai, urutkan berdasarkan shader. Idenya adalah untuk meminimalkan berapa kali Anda mengganti shader dalam bingkai, dengan menggambar semua objek dengan shader yang diberikan bersamaan. Hal ini karena beralih shader adalah operasi yang agak mahal (meskipun Anda pasti bisa melakukannya beberapa ratus atau seribu kali per frame, sehingga tidak benar-benar yang mahal).
Bahkan, Anda bisa melangkah lebih jauh dan mengurutkan jerat dengan shader pertama dan kedua materi. Yang dimaksud dengan "material", maksud saya adalah kombinasi shader dan satu set tekstur dan parameter untuk itu. Shader biasanya memiliki beberapa tekstur dan parameter numerik (disimpan dalam buffer konstan) yang dimasukkan ke dalamnya, jadi misalnya material batu bata dan material aspal mungkin menggunakan kode shader yang sama, hanya dengan tekstur yang berbeda.
Untuk menggambar, cukup putar di atas shader, atur setiap shader di ID3D11DeviceContext
, atur parameter apa saja (buffer konstan, tekstur, dll.), Lalu gambar objek. Dalam pseudocode, termasuk perbedaan shader / bahan yang saya sebutkan:
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(...)
Ada banyak lagi yang bisa dikatakan tentang mengelola objek, jerat, shader, tata letak input, buffer konstan, dll. Tetapi ini sudah cukup untuk membantu Anda memulai. :)