Pelabuhan GLSL

API Penting

Setelah Anda memindahkan kode yang membuat dan mengonfigurasi buffer dan objek shader Anda, saatnya untuk port kode di dalam shader tersebut dari Gl Shader Language (GLSL) OpenGL ES 2.0 ke Direct3D 11's High-level Shader Language (HLSL).

Di OpenGL ES 2.0, shader mengembalikan data setelah eksekusi menggunakan intrinsik seperti gl_Position, gl_FragColor, atau gl_FragData[n] (di mana n adalah indeks untuk target render tertentu). Dalam Direct3D, tidak ada intrinsik tertentu, dan shader mengembalikan data sebagai jenis pengembalian fungsi utama () masing-masing.

Data yang ingin Anda interpolasi antara tahap shader, seperti posisi simpul atau normal, ditangani melalui penggunaan deklarasi yang bervariasi . Namun, Direct3D tidak memiliki deklarasi ini; sebaliknya, data apa pun yang ingin Anda lewati di antara tahap shader harus ditandai dengan semantik HLSL. Semantik spesifik yang dipilih menunjukkan tujuan data, dan sedang. Misalnya, Anda akan mendeklarasikan data simpul yang ingin diinterpolasi di antara shader fragmen sebagai:

float4 vertPos : POSITION;

atau

float4 vertColor : COLOR;

Di mana POSITION adalah semantik yang digunakan untuk menunjukkan data posisi vertex. POSITION juga merupakan kasus khusus, karena setelah interpolasi, tidak dapat diakses oleh shader piksel. Oleh karena itu, Anda harus menentukan input ke shader piksel dengan SV_POSITION dan data simpul interpolasi akan ditempatkan dalam variabel itu.

float4 position : SV_POSITION;

Semantik dapat dinyatakan pada tubuh (utama) metode shader. Untuk shader piksel, SV_TARGET[n], yang menunjukkan target render, diperlukan pada metode bodi. (SV_TARGET tanpa default akhiran numerik untuk merender indeks target 0.)

Perhatikan juga bahwa shader simpul diperlukan untuk mengeluarkan nilai sistem SV_POSITION semantik. Semantik ini menyelesaikan data posisi simpul untuk mengkoordinasikan nilai di mana x adalah antara -1 dan 1, y adalah antara -1 dan 1, z dibagi dengan koordinat homogen asli w nilai (z / w), dan w adalah 1 dibagi dengan nilai w asli (1 / w). Shader piksel menggunakan SV_POSITION nilai sistem semantik untuk mengambil lokasi piksel di layar, di mana x antara 0 dan lebar target render dan y adalah antara 0 dan tinggi target render (masing-masing diimbangi oleh 0,5). Tingkat fitur 9_x shader piksel tidak dapat membaca dari nilai SV_POSITION.

Buffer konstan harus dinyatakan dengan cbuffer dan dikaitkan dengan register awal tertentu untuk pencarian.

Direct3D 11: Deklarasi buffer konstan HLSL

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix mvp;
};

Di sini, buffer konstan menggunakan register b0 untuk menahan buffer yang dikemas. Semua register disebut dalam formulir b #. Untuk informasi lebih lanjut tentang implementasi HLSL dari buffer konstan, register, dan pengepakan data, baca Shader Constants (HLSL).

Instruksi

Langkah 1: Port shader simpul

Dalam contoh OpenGL ES 2.0 sederhana kami, shader simpul memiliki tiga input: matriks 4x4 proyeksi model-tampilan konstan, dan dua vektor 4 koordinat. Kedua vektor ini mengandung posisi simpul dan warnanya. Shader mengubah vektor posisi menjadi koordinat perspektif dan menetapkannya ke gl_Position intrinsik untuk rasterisasi. Warna simpul disalin ke variabel yang bervariasi untuk interpolasi selama rasterisasi, juga.

OpenGL ES 2.0: Vertex shader untuk objek kubus (GLSL)

uniform mat4 u_mvpMatrix; 
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 destColor;

void main()
{           
  gl_Position = u_mvpMatrix * a_position;
  destColor = a_color;
}

Sekarang, dalam Direct3D, matriks proyeksi tampilan model konstan terkandung dalam buffer konstan yang dikemas pada register b0, dan posisi dan warna simpul secara khusus ditandai dengan semantik HLSL masing-masing yang sesuai: POSISI dan WARNA. Karena tata letak input kami menunjukkan pengaturan spesifik dari dua nilai simpul ini, Anda membuat struktur untuk menahannya dan mendeklarasikannya sebagai jenis parameter input pada fungsi bodi shader (utama). (Anda juga bisa menentukannya sebagai dua parameter individual, tetapi itu bisa menjadi rumit.) Anda juga menentukan jenis output untuk tahap ini, yang berisi posisi dan warna interpolasi, dan menyatakannya sebagai nilai pengembalian untuk fungsi tubuh shader simpul.

Direct3D 11: Vertex shader untuk objek kubus (HLSL)

cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
  matrix mvp;
};

// Per-vertex data used as input to the vertex shader.
struct VertexShaderInput
{
  float3 pos : POSITION;
  float3 color : COLOR;
};

// Per-vertex color data passed through the pixel shader.
struct PixelShaderInput
{
  float3 pos : SV_POSITION;
  float3 color : COLOR;
};

PixelShaderInput main(VertexShaderInput input)
{
  PixelShaderInput output;
  float4 pos = float4(input.pos, 1.0f); // add the w-coordinate

  pos = mul(mvp, projection);
  output.pos = pos;

  output.color = input.color;

  return output;
}

Tipe data output, PixelShaderInput, diisi selama rasterisasi dan diberikan ke shader fragmen (piksel).

Langkah 2: Port shader fragmen

Contoh shader fragmen kami di GLSL sangat sederhana: memberikan gl_FragColor intrinsik dengan nilai warna interpolasi. OpenGL ES 2.0 akan menuliskannya ke target render default.

OpenGL ES 2.0: Shader fragmen untuk objek kubus (GLSL)

varying vec4 destColor;

void main()
{
  gl_FragColor = destColor;
} 

Direct3D hampir sesederhana itu. Satu-satunya perbedaan yang signifikan adalah bahwa fungsi tubuh shader piksel harus mengembalikan nilai. Karena warnanya adalah nilai float 4-coordinate (RGBA), Anda menunjukkan float4 sebagai tipe return, lalu tentukan target render default sebagai SV_TARGET nilai sistem semantik.

Direct3D 11: Shader piksel untuk objek kubus (HLSL)

struct PixelShaderInput
{
  float4 pos : SV_POSITION;
  float3 color : COLOR;
};


float4 main(PixelShaderInput input) : SV_TARGET
{
  return float4(input.color, 1.0f);
}

Warna untuk piksel pada posisi ditulis ke target render. Sekarang, mari kita lihat cara menampilkan konten target render itu di Draw ke layar!

Langkah sebelumnya

Port buffer dan data simpul

Langkah selanjutnya

Gambar ke layar

Keterangan

Memahami semantik HLSL dan pengepakan buffer konstan dapat menghemat sedikit sakit kepala debugging, serta memberikan peluang pengoptimalan. Jika Anda mendapatkan kesempatan, baca sintaks variabel (HLSL),Introduction to Buffers in Direct3D 11, dan Cara: Buat Buffer Konstan. Namun, jika tidak, berikut adalah beberapa tips awal yang perlu diingat tentang semantik dan buffer konstan:

  • Selalu periksa kembali kode konfigurasi Direct3D perender Anda untuk memastikan bahwa struktur untuk buffer konstan Anda cocok dengan deklarasi struct cbuffer di HLSL Anda, dan bahwa jenis skalar komponen cocok di kedua deklarasi.
  • Dalam kode C++ perender Anda, gunakan jenis DirectXMath dalam deklarasi buffer konstan Anda untuk memastikan pengepakan data yang tepat.
  • Cara terbaik untuk menggunakan buffer konstan secara efisien adalah dengan mengatur variabel shader menjadi buffer konstan berdasarkan frekuensi pembaruannya. Misalnya, jika Anda memiliki beberapa data seragam yang diperbarui sekali per frame, dan data seragam lainnya yang diperbarui hanya saat kamera bergerak, pertimbangkan untuk memisahkan data tersebut menjadi dua buffer konstan terpisah.
  • Semantik yang lupa Anda terapkan atau yang telah Anda terapkan secara tidak benar akan menjadi sumber kesalahan kompilasi shader (FXC) anda yang paling awal. Periksa kembali mereka! Dokumen bisa sedikit membingungkan, karena banyak halaman dan sampel yang lebih lama mengacu pada versi semantik HLSL yang berbeda sebelum Direct3D 11.
  • Pastikan Anda tahu tingkat fitur Direct3D mana yang Anda targetkan untuk setiap shader. Semantik untuk fitur level 9_* berbeda dari yang untuk 11_1.
  • Semantik SV_POSITION menyelesaikan data posisi pasca-interpolasi terkait untuk mengkoordinasikan nilai di mana x berada antara 0 dan lebar target render, y adalah antara 0 dan tinggi target render, z dibagi dengan koordinat homogen asli w nilai (z / w), dan w adalah 1 dibagi dengan nilai w asli (1 / w).

Cara: port renderer OpenGL ES 2.0 sederhana ke Direct3D 11

Port objek shader

Port buffer dan data simpul

Gambar ke layar