Menggunakan Shader di Direct3D 10
Alur ini memiliki tiga tahap shader dan masing-masing diprogram dengan shader HLSL. Semua shader Direct3D 10 ditulis dalam HLSL, menargetkan model shader 4.
Perbedaan antara Direct3D 9 dan Direct3D 10:
- Tidak seperti model shader Direct3D 9 yang dapat ditulis dalam bahasa perakitan menengah, shader model 4.0 shader hanya ditulis dalam HLSL. Kompilasi offline shader ke dalam bytecode yang dapat dikonsumsi perangkat masih didukung, dan direkomendasikan untuk sebagian besar skenario.
Contoh ini hanya menggunakan shader puncak. Karena semua shader dibangun dari inti shader umum, mempelajari cara menggunakan shader vertex sangat mirip dengan menggunakan geometri atau pixel shader.
Setelah Anda menulis shader HLSL (contoh ini menggunakan vertex shader HLSLWithoutFX.vsh), Anda harus menyiapkannya untuk tahap alur tertentu yang akan menggunakannya. Untuk melakukan ini, Anda perlu:
Langkah-langkah ini perlu diulang untuk setiap shader dalam alur.
Mengkompilasi Shader
Langkah pertama adalah mengkompilasi shader, untuk memeriksa untuk melihat bahwa Anda telah mengkodekan pernyataan HLSL dengan benar. Ini dilakukan dengan memanggil D3D10CompileShader dan menyediakannya dengan beberapa parameter seperti yang ditunjukkan di sini:
IPD3D10Blob * pBlob;
// Compile the vertex shader from the file
D3D10CompileShader( strPath, strlen( strPath ), "HLSLWithoutFX.vsh",
NULL, NULL, "Ripple", "vs_4_0", dwShaderFlags, &pBlob, NULL );
Fungsi ini mengambil parameter berikut:
Nama file ( dan panjang string nama dalam byte ) yang berisi shader. Contoh ini hanya menggunakan shader vertex (dalam file HLSLWithoutFX.vsh di mana ekstensi file .vsh adalah singkatan untuk shader vertex).
Nama fungsi shader. Contoh ini mengkompilasi shader vertex dari fungsi Ripple yang mengambil satu input dan mengembalikan struct output (fungsinya berasal dari sampel HLSLWithoutFX):
VS_OUTPUT Ripple( in float2 vPosition : POSITION )
Penunjuk ke semua makro yang digunakan oleh shader. Gunakan D3D10_SHADER_MACRO untuk membantu menentukan makro Anda; cukup buat string nama yang berisi semua nama makro (dengan setiap nama dipisahkan oleh spasi) dan string definisi (dengan setiap isi makro dipisahkan oleh spasi). Kedua string harus dihentikan NULL.
Pointer ke file lain yang perlu Anda sertakan untuk mengkompilasi shader Anda. Ini menggunakan antarmuka ID3D10Include yang memiliki dua metode yang diterapkan pengguna: Buka dan Tutup. Untuk membuat pekerjaan ini, Anda harus mengimplementasikan isi metode Buka dan Tutup; dalam metode Buka tambahkan kode yang akan Anda gunakan untuk membuka file apa pun yang Anda inginkan, dalam fungsi Tutup tambahkan kode untuk menutup file ketika Anda selesai dengannya.
Nama fungsi shader untuk dikompilasi. Shader ini mengkompilasi fungsi Ripple.
Profil shader untuk ditargetkan saat mengkompilasi. Karena Anda dapat mengkompilasi fungsi menjadi vertex, geometri, atau pixel shader, profil memberi tahu pengkompilasi jenis shader mana dan model shader mana yang akan dibandingkan dengan kode.
Bendera pengkompilasi shader. Bendera ini memberi tahu pengkompilasi informasi apa yang akan dimasukkan ke dalam output yang dikompilasi dan bagaimana Anda ingin kode output dioptimalkan: untuk kecepatan, untuk debug, dll. Lihat Konstanta Efek (Direct3D 10) untuk daftar bendera yang tersedia. Sampel berisi beberapa kode yang dapat Anda gunakan untuk mengatur nilai bendera pengkompilasi untuk proyek Anda - ini terutama pertanyaan tentang apakah Anda ingin menghasilkan informasi debug atau tidak.
Penunjuk ke buffer yang berisi kode shader yang dikompilasi. Buffer juga berisi informasi debug dan tabel simbol yang disematkan yang diminta oleh bendera pengkompilasi.
Penunjuk ke buffer yang berisi daftar kesalahan dan peringatan yang ditemui selama kompilasi, yang merupakan pesan yang sama yang akan Anda lihat di output debug jika Anda menjalankan debugger saat mengkompilasi shader. NULL adalah nilai yang dapat diterima ketika Anda tidak ingin kesalahan dikembalikan ke buffer.
Jika shader berhasil dikompilasi, penunjuk ke kode shader dikembalikan sebagai antarmuka ID3D10Blob. Ini disebut antarmuka Blob karena pointer adalah ke lokasi dalam memori yang terdiri dari array DWORD. Antarmuka disediakan sehingga Anda bisa mendapatkan penunjuk ke shader yang dikompilasi yang akan Anda butuhkan di langkah berikutnya.
Dimulai dengan SDK Desember 2006, pengkompilasi DirectX 10 HLSL sekarang menjadi pengkompilasi default di DirectX 9 dan DirectX 10. Lihat Alat Pengkompilasi Efek untuk detailnya.
Mendapatkan Pointer ke Shader yang Dikompilasi
Beberapa metode API memerlukan penunjuk ke shader yang dikompilasi. Argumen ini biasanya disebut pShaderBytecode karena menunjuk ke shader yang dikompilasi yang direpresentasikan sebagai urutan kode byte. Untuk mendapatkan penunjuk ke shader yang dikompilasi, pertama-tama kompilasi shader dengan memanggil D3D10CompileShader atau fungsi serupa. Jika kompilasi berhasil, shader yang dikompilasi dikembalikan dalam antarmuka ID3D10Blob . Terakhir, gunakan metode GetBufferPointer untuk mengembalikan penunjuk.
Membuat Objek Shader
Setelah shader dikompilasi, panggil CreateVertexShader untuk membuat objek shader:
ID3D10VertexShader ** ppVertexShader
ID3D10Blob pBlob;
// Create the vertex shader
hr = pd3dDevice->CreateVertexShader( (DWORD*)pBlob->GetBufferPointer(),
pBlob->GetBufferSize(), &ppVertexShader );
// Release the pointer to the compiled shader once you are done with it
pBlob->Release();
Untuk membuat objek shader, teruskan penunjuk ke shader yang dikompilasi ke CreateVertexShader. Karena Anda harus berhasil mengkompilasi shader terlebih dahulu, panggilan ini hampir pasti akan berlalu, kecuali Anda memiliki masalah memori pada komputer Anda.
Anda dapat membuat objek shader sebanyak yang Anda suka dan cukup simpan pointer ke objek tersebut. Mekanisme yang sama ini berfungsi untuk geometri dan shader piksel dengan asumsi Anda cocok dengan profil shader (saat Anda memanggil metode kompilasi) ke nama antarmuka (saat Anda memanggil metode buat).
Mengatur Objek Shader
Langkah terakhir adalah mengatur shader ke tahap alur. Karena ada tiga tahap shader dalam alur, Anda harus melakukan tiga panggilan API, satu untuk setiap tahap.
// Set a vertex shader
pd3dDevice->VSSetShader( g_pVS10 );
Panggilan ke VSSetShader membawa penunjuk ke shader vertex yang dibuat di langkah 1. Ini mengatur shader di perangkat. Tahap shader vertex sekarang diinisialisasi dengan kode shader vertex-nya, yang tersisa adalah menginisialisasi variabel shader apa pun.
Ulangi untuk semua 3 Tahap Shader
Ulangi serangkaian langkah yang sama ini untuk membangun vertex atau shader piksel atau bahkan shader geometri yang menghasilkan shader piksel.