Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Game Universal Windows Platform (UWP) 3-D biasanya menggunakan poligon untuk mewakili objek dan permukaan dalam game. Daftar simpul yang menyusun struktur objek dan permukaan poligonal ini disebut mesh. Di sini, kami membuat jala dasar untuk objek kubus dan menyediakannya ke alur shader untuk penyajian dan tampilan.
Penting Kode contoh yang disertakan di sini menggunakan tipe data (seperti DirectX::XMFLOAT3 dan DirectX::XMFLOAT4X4) dan metode inline yang dideklarasikan dalam DirectXMath.h. Jika Anda memotong dan menempelkan kode ini, #include <DirectXMath.h> dalam proyek Anda.
Apa yang perlu Anda ketahui
Teknologi
Prasyarat
- Pengetahuan dasar tentang aljabar linier dan sistem koordinat 3-D
- Templat Direct3D Visual Studio 2015 atau yang lebih baru
Petunjuk
Langkah-langkah ini akan menunjukkan kepada Anda cara membuat kubus jejaring dasar.
Langkah 1: Buat jaring untuk model
Di sebagian besar game, mesh untuk objek game dimuat dari file yang berisi data vertex tertentu. Urutan simpul ini tergantung pada aplikasi, tetapi biasanya diserialisasikan sebagai strip atau kipas. Data vertex dapat berasal dari sumber perangkat lunak apa pun, atau dapat dibuat secara manual. Tergantung pada permainan Anda untuk menafsirkan data dengan cara yang dapat diproses secara efektif oleh vertex shader.
Dalam contoh kami, kami menggunakan mesh sederhana untuk kubus. Kubus, seperti jala objek pada tahap ini dalam jalur pemrosesan, diwakili menggunakan sistem koordinatnya sendiri. Shader vertex mengambil koordinatnya dan, dengan menerapkan matriks transformasi yang Anda berikan, mengembalikan proyeksi tampilan 2-D akhir dalam sistem koordinat homogen.
Definisikan jaring untuk kubus. (Atau muat dari file. Itu terserah Anda!)
SimpleCubeVertex cubeVertices[] =
{
{ DirectX::XMFLOAT3(-0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f) }, // +Y (top face)
{ DirectX::XMFLOAT3( 0.5f, 0.5f, -0.5f), DirectX::XMFLOAT3(1.0f, 1.0f, 0.0f) },
{ DirectX::XMFLOAT3( 0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f) },
{ DirectX::XMFLOAT3(-0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3(0.0f, 1.0f, 1.0f) },
{ DirectX::XMFLOAT3(-0.5f, -0.5f, 0.5f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f) }, // -Y (bottom face)
{ DirectX::XMFLOAT3( 0.5f, -0.5f, 0.5f), DirectX::XMFLOAT3(1.0f, 0.0f, 1.0f) },
{ DirectX::XMFLOAT3( 0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f) },
{ DirectX::XMFLOAT3(-0.5f, -0.5f, -0.5f), DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f) },
};
Sistem koordinat kubus menempatkan pusat kubus di asalnya, dengan sumbu y berjalan atas ke bawah menggunakan sistem koordinat sebelah kiri. Nilai koordinat dinyatakan sebagai nilai mengambang 32-bit antara -1 dan 1.
Dalam setiap pasangan dalam tanda kurung, kelompok nilai DirectX::XMFLOAT3 kedua menetapkan warna yang terkait dengan puncak sebagai nilai RGB. Misalnya, puncak pertama pada (-0,5, 0,5, -0,5) memiliki warna hijau penuh (nilai G diatur ke 1,0, dan nilai "R" dan "B" diatur ke 0).
Oleh karena itu, Anda memiliki 8 simpul, masing-masing dengan warna tertentu. Setiap pasangan vertex/warna merupakan data lengkap untuk sebuah vertex dalam contoh kita. Ketika Anda menentukan buffer vertex milik kami, Anda harus mengingat tata letak khusus ini. Kami menyediakan tata letak input ini ke shader vertex sehingga dapat memahami data vertex Anda.
Langkah 2: Siapkan tata letak input
Sekarang, Anda memiliki titik dalam memori. Tetapi, perangkat grafis Anda memiliki memorinya sendiri, dan Anda menggunakan Direct3D untuk mengaksesnya. Untuk memasukkan data vertex Anda ke perangkat grafis untuk diproses, Anda perlu mempersiapkannya dengan benar: Anda harus menyatakan bagaimana data vertex disusun sehingga perangkat grafis dapat menafsirkannya ketika menerimanya dari game Anda. Untuk melakukannya, Anda menggunakan ID3D11InputLayout.
Deklarasikan dan atur tata letak input untuk vertex buffer.
const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
ComPtr<ID3D11InputLayout> inputLayout;
m_d3dDevice->CreateInputLayout(
basicVertexLayoutDesc,
ARRAYSIZE(basicVertexLayoutDesc),
vertexShaderBytecode->Data,
vertexShaderBytecode->Length,
&inputLayout)
);
Dalam kode ini, Anda menentukan tata letak untuk simpul, khususnya, data apa yang dimuat setiap elemen dalam daftar vertex. Di sini, di basicVertexLayoutDesc, Anda menentukan dua komponen data:
POSITION: Ini adalah semantik HLSL untuk data posisi yang disediakan untuk shader. Dalam kode ini, ini adalah DirectX::XMFLOAT3, atau lebih khusus lagi, struktur dengan nilai floating point 3 32-bit yang sesuai dengan koordinat 3D (x, y, z). Anda juga dapat menggunakan float4 jika Anda menyediakan koordinat "w" homogen, dan dalam hal ini, Anda menentukan DXGI_FORMAT_R32G32B32A32_FLOAT. Apakah Anda menggunakan DirectX::XMFLOAT3 atau float4 sesuai dengan kebutuhan spesifik game Anda. Pastikan bahwa data vertex untuk mesh Anda benar-benar sesuai dengan format yang sedang Anda gunakan!
Setiap nilai koordinat dinyatakan sebagai nilai titik mengambang antara -1 dan 1, di ruang koordinat objek. Ketika shader vertex selesai, vertex yang diubah berada di ruang proyeksi tampilan homogen (dengan koreksi perspektif).
"Tetapi nilai enumerasi menunjukkan RGB, bukan XYZ!" Anda dengan cerdas mencatat. Mata yang bagus! Dalam kedua kasus data warna dan data koordinat, Anda biasanya menggunakan 3 atau 4 nilai komponen, jadi mengapa tidak menggunakan format yang sama untuk keduanya? Semantik HLSL, bukan nama format, menunjukkan bagaimana shader memperlakukan data.
COLOR: Ini adalah semantik HLSL untuk data warna. Seperti POSITION, ini terdiri dari 3 nilai floating point 32-bit (DirectX::XMFLOAT3). Setiap nilai berisi komponen warna: merah (r), biru (b), atau hijau (g), dinyatakan sebagai angka mengambang antara 0 dan 1.
COLOR biasanya dikembalikan sebagai nilai RGBA 4 komponen pada akhir pipeline shader. Untuk contoh ini, Anda akan mengatur nilai alfa "A" menjadi 1,0 (keburaman maksimum) dalam alur shader untuk semua piksel.
Untuk daftar lengkap format, lihat DXGI_FORMAT. Untuk daftar lengkap semantik HLSL, lihat Semantik.
Panggil ID3D11Device::CreateInputLayout dan buat tata letak input pada perangkat Direct3D. Sekarang, Anda perlu membuat buffer yang benar-benar dapat menyimpan data!
Langkah 3: Isi vertex buffer
Buffer verteks berisi daftar verteks untuk setiap segitiga pada mesh. Setiap puncak harus unik dalam daftar ini. Dalam contoh kami, Anda memiliki 8 simpul untuk kubus. Vertex shader berjalan pada perangkat grafis, membaca dari vertex buffer, dan menginterpretasikan data berdasarkan tata letak input yang Anda tentukan di langkah sebelumnya.
Dalam contoh berikutnya, Anda memberikan deskripsi dan sub sumber daya untuk buffer, yang memberi tahu Direct3D sejumlah hal tentang pemetaan fisik data vertex dan cara memperlakukannya dalam memori pada perangkat grafis. Ini diperlukan karena Anda menggunakan generik ID3D11Bufferyang dapat berisi apa pun! Struktur D3D11_BUFFER_DESC dan D3D11_SUBRESOURCE_DATA disediakan untuk memastikan bahwa Direct3D memahami tata letak memori fisik buffer, termasuk ukuran setiap elemen vertex dalam buffer serta ukuran maksimum daftar vertex. Anda juga dapat mengontrol akses ke memori buffer di sini dan bagaimana itu dilalui, tetapi itu sedikit di luar cakupan tutorial ini.
Setelah mengonfigurasi buffer, Anda memanggil ID3D11Device::CreateBuffer untuk benar-benar membuatnya. Jelas, jika Anda memiliki lebih dari satu objek, buat buffer untuk setiap model unik.
Deklarasikan dan buat buffer vertex.
D3D11_BUFFER_DESC vertexBufferDesc = {0};
vertexBufferDesc.ByteWidth = sizeof(SimpleCubeVertex) * ARRAYSIZE(cubeVertices);
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
vertexBufferData.pSysMem = cubeVertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
ComPtr<ID3D11Buffer> vertexBuffer;
m_d3dDevice->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
&vertexBuffer);
Banyak simpul dimuat. Tapi apa urutan pemrosesan simpul ini? Itu ditangani saat Anda memberikan daftar indeks ke titik—urutan indeks ini menentukan urutan di mana vertex shader memprosesnya.
Langkah 4: Mengisi buffer indeks
Sekarang, Anda memberikan daftar indeks untuk setiap simpul. Indeks ini sesuai dengan posisi verteks dalam buffer verteks, dimulai dengan 0. Untuk membantu Anda memvisualisasikan ini, pertimbangkan bahwa setiap vertex unik dalam mesh Anda memiliki nomor unik yang diterapkan padanya, seperti ID. ID ini adalah posisi bilangan bulat vertex di penyangga vertex.
Dalam contoh kubus kami, Anda memiliki 8 simpul, yang membuat 6 quad untuk sisi. Anda membagi quad menjadi segitiga, untuk total 12 segitiga yang menggunakan 8 simpul kami. Dengan 3 simpul per segitiga, Anda memiliki 36 entri dalam buffer indeks kami. Dalam contoh kami, pola indeks ini dikenal sebagai daftar segitiga, dan Anda menunjukkannya ke Direct3D sebagai D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST saat Anda mengatur topologi primitif.
Ini mungkin cara yang paling tidak efisien untuk mencantumkan indeks, karena ada banyak redundansi ketika segitiga berbagi titik dan sisi. Misalnya, ketika segitiga berbagi sisi dalam bentuk ketupat, Anda mencantumkan 6 indeks untuk empat simpul, seperti ini:
- Segitiga 1: [0, 1, 2]
- Segitiga 2: [0, 2, 3]
Dalam topologi strip atau kipas, Anda mengatur simpul dengan cara yang menghilangkan banyak sisi berlebihan selama traversal (seperti sisi dari indeks 0 hingga indeks 2 dalam gambar.) Untuk mesh yang besar, ini secara dramatis mengurangi berapa banyak vertex shader yang dijalankan, dan meningkatkan performa secara signifikan. Namun, kita akan membuatnya sederhana dan tetap menggunakan daftar segitiga.
Tentukan indeks untuk penyangga verteks sebagai topologi daftar segitiga sederhana.
unsigned short cubeIndices[] =
{ 0, 1, 2,
0, 2, 3,
4, 5, 6,
4, 6, 7,
3, 2, 5,
3, 5, 4,
2, 1, 6,
2, 6, 5,
1, 7, 6,
1, 0, 7,
0, 3, 4,
0, 4, 7 };
Tiga puluh enam elemen indeks dalam buffer sangat berlebihan ketika Anda hanya memiliki 8 simpul! Jika Anda memilih untuk menghilangkan beberapa redundansi dan menggunakan jenis daftar vertex yang berbeda, seperti strip atau kipas, Anda harus menentukan jenis tersebut saat memberikan nilai D3D11_PRIMITIVE_TOPOLOGY tertentu ke metode ID3D11DeviceContext::IASetPrimitiveTopology .
Untuk informasi selengkapnya tentang teknik daftar indeks yang berbeda, lihat Topologi Primitif.
Langkah 5: Buat buffer konstan untuk matriks transformasi Anda
Sebelum Anda dapat mulai memproses titik sudut, Anda perlu memberikan matriks transformasi yang akan diterapkan (dikalikan) ke setiap titik sudut saat proses berjalan. Untuk sebagian besar game 3-D, ada tiga di antaranya:
- Matriks 4x4 yang berubah dari sistem koordinat objek (model) ke sistem koordinat dunia secara keseluruhan.
- Matriks 4x4 yang mentransformasi dari sistem koordinat dunia ke sistem koordinat kamera.
- Matriks 4x4 yang mentransformasikan dari sistem koordinat kamera ke sistem koordinat proyeksi tampilan 2-D.
Matriks ini diteruskan ke shader dalam konstanta buffer . Buffer konstan adalah wilayah memori yang tetap konstan selama eksekusi tahap berikutnya dari pipeline shader, yang dapat diakses langsung oleh shader melalui kode HLSL Anda. Anda menentukan setiap buffer konstanta dua kali: pertama dalam kode C++ game Anda, dan (setidaknya) satu kali dalam sintaks HLSL seperti C untuk kode shader Anda. Dua deklarasi harus langsung sesuai dalam aspek jenis dan perataan data. Sangat mudah untuk memperkenalkan kesalahan yang sulit ditemukan ketika shader menggunakan deklarasi HLSL untuk menginterpretasikan data yang dideklarasikan dalam C++, dan jenis data tidak sesuai atau penyelarasan data tidak tepat!
Buffer konstan tidak diubah oleh HLSL. Anda dapat mengubahnya saat game memperbarui data tertentu. Seringkali, pengembang game membuat 4 kelas buffer konstan: satu jenis untuk pembaruan per bingkai; satu jenis untuk pembaruan per model/objek; satu jenis untuk pembaruan per refresh status game; dan satu jenis untuk data yang tidak pernah berubah selama masa pakai permainan.
Dalam contoh ini, kita hanya memiliki satu yang tidak pernah berubah: data DirectX::XMFLOAT4X4 untuk tiga matriks.
Nota Contoh kode yang disajikan di sini menggunakan matriks utama kolom. Anda dapat menggunakan matriks utama baris sebagai gantinya dengan menggunakan kata kunci row_major di HLSL, dan memastikan data matriks sumber Anda juga merupakan row-major. DirectXMath menggunakan matriks berorientasi-baris dan dapat digunakan langsung dengan matriks HLSL yang ditentukan dengan kata kunci row_major.
Deklarasikan dan buat buffer konstan untuk tiga matriks yang Anda gunakan untuk mengubah setiap puncak.
struct ConstantBuffer
{
DirectX::XMFLOAT4X4 model;
DirectX::XMFLOAT4X4 view;
DirectX::XMFLOAT4X4 projection;
};
ComPtr<ID3D11Buffer> m_constantBuffer;
ConstantBuffer m_constantBufferData;
// ...
// Create a constant buffer for passing model, view, and projection matrices
// to the vertex shader. This allows us to rotate the cube and apply
// a perspective projection to it.
D3D11_BUFFER_DESC constantBufferDesc = {0};
constantBufferDesc.ByteWidth = sizeof(m_constantBufferData);
constantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDesc.CPUAccessFlags = 0;
constantBufferDesc.MiscFlags = 0;
constantBufferDesc.StructureByteStride = 0;
m_d3dDevice->CreateBuffer(
&constantBufferDesc,
nullptr,
&m_constantBuffer
);
m_constantBufferData.model = DirectX::XMFLOAT4X4( // Identity matrix, since you are not animating the object
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
);
// Specify the view (camera) transform corresponding to a camera position of
// X = 0, Y = 1, Z = 2.
m_constantBufferData.view = DirectX::XMFLOAT4X4(
-1.00000000f, 0.00000000f, 0.00000000f, 0.00000000f,
0.00000000f, 0.89442718f, 0.44721359f, 0.00000000f,
0.00000000f, 0.44721359f, -0.89442718f, -2.23606800f,
0.00000000f, 0.00000000f, 0.00000000f, 1.00000000f);
Nota Anda biasanya mendeklarasikan matriks proyeksi saat menyiapkan sumber daya khusus perangkat, karena hasil perkalian dengannya harus cocok dengan parameter ukuran viewport 2-D saat ini (yang sering sesuai dengan tinggi piksel dan lebar tampilan). Jika hal-hal tersebut berubah, Anda harus menskalakan nilai koordinat x dan y secara sesuai.
// Finally, update the constant buffer perspective projection parameters
// to account for the size of the application window. In this sample,
// the parameters are fixed to a 70-degree field of view, with a depth
// range of 0.01 to 100.
float xScale = 1.42814801f;
float yScale = 1.42814801f;
if (backBufferDesc.Width > backBufferDesc.Height)
{
xScale = yScale *
static_cast<float>(backBufferDesc.Height) /
static_cast<float>(backBufferDesc.Width);
}
else
{
yScale = xScale *
static_cast<float>(backBufferDesc.Width) /
static_cast<float>(backBufferDesc.Height);
}
m_constantBufferData.projection = DirectX::XMFLOAT4X4(
xScale, 0.0f, 0.0f, 0.0f,
0.0f, yScale, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, -0.01f,
0.0f, 0.0f, -1.0f, 0.0f
);
Saat Anda berada di sini, atur buffer puncak dan indeks padaID3D11DeviceContext, ditambah topologi yang Anda gunakan.
// Set the vertex and index buffers, and specify the way they define geometry.
UINT stride = sizeof(SimpleCubeVertex);
UINT offset = 0;
m_d3dDeviceContext->IASetVertexBuffers(
0,
1,
vertexBuffer.GetAddressOf(),
&stride,
&offset);
m_d3dDeviceContext->IASetIndexBuffer(
indexBuffer.Get(),
DXGI_FORMAT_R16_UINT,
0);
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
Baiklah! Perakitan input selesai. Semuanya ada di tempat untuk penyajian. Mari kita mulai menjalankan vertex shader tersebut.
Langkah 6: Memproses jala dengan vertex shader
Sekarang setelah Anda memiliki penyangga verteks dengan verteks yang menentukan mesh Anda, dan penyangga indeks yang menentukan urutan di mana verteks diproses, Anda mengirimkannya ke shader verteks. Kode shader vertex, yang diungkapkan sebagai bahasa shader tingkat tinggi yang telah dikompilasi, dijalankan satu kali untuk setiap titik di buffer vertex, memungkinkan Anda melakukan transformasi pada setiap titik. Hasil akhir biasanya adalah proyeksi 2-D.
(Apakah shader vertex Anda sudah dimuat? Jika belum, silakan tinjau Cara memuat sumber daya di game DirectX Anda.)
Di sini, Anda membuat vertex shader...
// Set the vertex and pixel shader stage state.
m_d3dDeviceContext->VSSetShader(
vertexShader.Get(),
nullptr,
0);
... dan mengatur buffer konstanta.
m_d3dDeviceContext->VSSetConstantBuffers(
0,
1,
m_constantBuffer.GetAddressOf());
Berikut adalah kode shader vertex yang menangani transformasi dari koordinat objek ke koordinat dunia lalu ke sistem koordinat proyeksi tampilan 2-D. Anda juga menerapkan beberapa pencahayaan per-vertex sederhana agar tampak lebih cantik. Ini masuk ke file HLSL vertex shader Anda (SimplerVertexShader.hlsl, dalam contoh ini).
cbuffer simpleConstantBuffer : register( b0 )
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
DirectX::XMFLOAT3 pos : POSITION;
DirectX::XMFLOAT3 color : COLOR;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float4 color : COLOR;
};
PixelShaderInput SimpleVertexShader(VertexShaderInput input)
{
PixelShaderInput vertexShaderOutput;
float4 pos = float4(input.pos, 1.0f);
// Transform the vertex position into projection space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
vertexShaderOutput.pos = pos;
// Pass the vertex color through to the pixel shader.
vertexShaderOutput.color = float4(input.color, 1.0f);
return vertexShaderOutput;
}
Lihat cbuffer di bagian atas? Itu adalah analog HLSL ke buffer konstanta yang sama yang kami deklarasikan dalam kode C++ kami sebelumnya. Dan VertexShaderInputstruct? Kenapa, itu terlihat seperti tata letak input dan deklarasi data verteks Anda! Penting bahwa deklarasi buffer konstan dan data vertex dalam kode C++ Anda cocok dengan deklarasi dalam kode HLSL Anda—termasuk penanda, jenis, dan perataan data.
PixelShaderInput menentukan tata letak data yang dikembalikan oleh fungsi utama dari vertex shader. Setelah selesai memproses simpul, Anda akan mengembalikan posisi simpul di ruang proyeksi 2-D dan warna yang digunakan untuk pencahayaan per-simpul. Kartu grafis menggunakan data yang dihasilkan oleh shader untuk menghitung "fragmen" (kemungkinan piksel) yang harus diwarnai ketika shader piksel dijalankan dalam tahap berikut dalam alur.
Langkah 7: Meneruskan mesh melalui shader piksel
Biasanya, pada tahap ini dalam alur grafis, Anda melakukan operasi per piksel pada permukaan objek yang diproyeksikan yang terlihat. (Orang menyukai tekstur.) Namun, untuk tujuan contoh, Anda cukup melewati tahap ini.
Pertama, kita buat dulu instans shader piksel. Shader piksel dijalankan untuk setiap piksel dalam proyeksi 2-D adegan Anda, untuk menetapkan warna pada piksel tersebut. Dalam hal ini, kami meneruskan warna untuk piksel yang dikembalikan oleh shader vertex langsung melalui.
Tentukan shader piksel.
m_d3dDeviceContext->PSSetShader( pixelShader.Get(), nullptr, 0 );
Tentukan shader piksel passthrough di HLSL.
struct PixelShaderInput
{
float4 pos : SV_POSITION;
};
float4 SimplePixelShader(PixelShaderInput input) : SV_TARGET
{
// Draw the entire triangle yellow.
return float4(1.0f, 1.0f, 0.0f, 1.0f);
}
Letakkan kode ini dalam file HLSL yang terpisah dari vertex shader HLSL (seperti SimplePixelShader.hlsl). Kode ini dijalankan satu kali untuk setiap piksel yang terlihat di viewport Anda (representasi dalam memori dari bagian layar yang Anda gambar), yang, dalam hal ini, memetakan ke seluruh layar. Sekarang, alur grafis Anda benar-benar ditentukan!
Langkah 8: Merasterisasi dan menampilkan mesh
Mari kita jalankan jalur prosesnya. Ini mudah: panggil ID3D11DeviceContext::DrawIndexed.
Gambar kubus itu!
// Draw the cube.
m_d3dDeviceContext->DrawIndexed( ARRAYSIZE(cubeIndices), 0, 0 );
Di dalam kartu grafis, setiap vertex diproses dalam urutan yang ditentukan dalam buffer indeks Anda. Setelah kode Anda menjalankan shader vertex dan fragmen 2-D ditentukan, shader piksel dipanggil dan segitiga diwarnai.
Sekarang, letakkan kubus di layar.
Tampilkan buffer bingkai tersebut pada layar.
// Present the rendered image to the window. Because the maximum frame latency is set to 1,
// the render loop is generally throttled to the screen refresh rate, typically around
// 60 Hz, by sleeping the app on Present until the screen is refreshed.
m_swapChain->Present(1, 0);
Dan anda sudah selesai! Untuk adegan yang dipenuhi oleh banyak model, gunakan beberapa buffer verteks dan indeks, dan Anda bahkan mungkin memerlukan shader yang berbeda untuk berbagai jenis model. Ingatlah bahwa setiap model memiliki sistem koordinatnya sendiri, dan Anda perlu mengubahnya ke sistem koordinat dunia bersama menggunakan matriks yang Anda tentukan dalam buffer konstan.
Komentar
Topik ini mencakup pembuatan dan tampilan geometri sederhana yang Anda buat sendiri. Untuk informasi selengkapnya tentang memuat geometri yang lebih kompleks dari file dan mengonversinya ke format objek buffer vertex khusus sampel (.vbo), lihat Cara memuat sumber daya di game DirectX Anda.
Topik terkait