Permukaan Shader dengan DX11 / OpenGL Inti Tesselasi
Memahami kinerja naungan

Menulis naungan untuk API grafis yang berbeda

Dalam beberapa kasus, ada perbedaan dalam bagaimana rendering grafis berperilaku antara API grafis yang berbeda. Sebagian besar waktu Editor Unity menyembunyikan perbedaan, tetapi ada beberapa situasi di mana Editor tidak dapat melakukan ini untuk Anda. Situasi ini, dan tindakan yang perlu Anda ambil jika terjadi, tercantum di bawah ini.

Render Tekstur koordinat

Konvensi koordinat Tekstur vertikal berbeda antara dua jenis platform: Direct3D-like dan OpenGL-like.

  • Direct3D-like: Koordinat adalah 0 di bagian atas dan meningkatkan ke bawah. Ini berlaku untuk Direct3D, Logam dan konsol.
  • OpenGL-like: Koordinat adalah 0 di bagian bawah dan meningkatkan ke atas. Ini berlaku untuk OpenGL dan OpenGL ES.

Perbedaan ini cenderung tidak memiliki efek pada proyek Anda, selain ketika rendering menjadi Render TeksturJenis Tekstur khusus yang diciptakan dan diperbarui pada runtime. Untuk menggunakannya, pertama membuat Tekstur Render baru dan menunjuk salah satu Kamera Anda untuk membuatnya. Kemudian Anda dapat menggunakan Tekstur Render dalam Bahan seperti Tekstur biasa. More info
Lihat di Glossary
. Ketika rendering ke dalam Tekstur pada platform langsung3D-seperti, terbalik secara internal Unity rendering terbalik. Ini membuat konvensi cocok antara platform, dengan platform OpenGL-seperti konvensi standar.

Efek Gambar dan rendering di ruang UV adalah dua kasus umum di ShadersProgram yang berjalan di GPU. More info
Lihat di Glossary
di mana Anda perlu mengambil tindakan untuk memastikan bahwa konvensi koordinat yang berbeda tidak membuat masalah dalam proyek Anda.

Efek Gambar

Ketika Anda menggunakan dan anti-aliasing, Tekstur sumber yang dihasilkan untuk Efek Gambar tidak dipotong sesuai dengan Konvensi platform TerbukaGL-seperti. Dalam hal ini, render Unity ke layar untuk mendapatkan anti-aliasing dan kemudian menyelesaikan rendering ke Tekstur Render untuk pemrosesan lebih lanjut dengan Efek Gambar.

Jika Efek Gambar Anda adalah salah satu sederhana yang memproses satu Tekstur Render pada waktu, Grafik Login berurusan dengan koordinat yang tidak konsisten. Namun, jika Anda memproses lebih dari satu Render Tekstur bersama-sama di Anda, Tekstur Render cenderung keluar pada orientasi vertikal yang berbeda di platform yang mirip Direct3D dan ketika Anda menggunakan anti-aliasing. Untuk menstandardisasi koordinat, Anda perlu secara manual “flip” layar Tekstur terbalik dalam Vertex ShaderProgram yang berjalan pada setiap simpul model 3D ketika model sedang diberikan. More info
Lihat di Glossary
Anda sehingga sesuai dengan standar koordinat OpenGL-like.

Sampel kode berikut menunjukkan cara melakukan ini:

// Flip sampling of the Texture: 
// The main Texture
// texel size will have negative Y).

#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
        uv.y = 1-uv.y;
#endif

Situasi serupa terjadi dengan GrabPass. Tekstur render yang dihasilkan mungkin tidak benar-benar dimatikan di platform Direct3D-like (non-OpenGL-like). Jika sampel kode Shader AmbilPass Tekstur, gunakan fungsi ComputeGrabScreenPos dari file UnityCG termasuk.

Pengirim di ruang UV

Ketika rendering di ruang berkoordinasi Tekstur (UV) untuk efek atau alat khusus, Anda mungkin perlu menyesuaikan Anda Shaders sehingga rendering konsisten antara sistem Direct3D-like dan OpenGL-like. Anda juga mungkin perlu menyesuaikan rendering Anda antara rendering ke layar dan rendering ke Tekstur. Sesuaikan ini dengan membalikkan proyeksi Direct3D-seperti terbalik sehingga koordinatnya sesuai dengan koordinat proyeksi OpenGL-like.

variabel built-in ProjectionParams.x mengandung nilai +1 atau –1. -1 menunjukkan proyeksi telah dibalik ke bawah untuk mencocokkan koordinat proyeksi TerbukaGL-seperti, sementara +1 menunjukkan itu belum selesai. Anda dapat memeriksa nilai ini di Shaders Anda dan kemudian melakukan tindakan yang berbeda. Contoh di bawah ini memeriksa jika proyeksi telah dibalik dan, jika demikian, flips dan kemudian kembali koordinat UV untuk mencocokkan.

float4 vert(float2 uv : TEXCOORD0) : SV_POSITION
{
    float4 pos;
    pos.xy = uv;
    // This example is rendering with upside-down flipped projection,
    // so flip the vertical UV coordinate too
    if (_ProjectionParams.x < 0)
        pos.y = 1 - pos.y;
    pos.z = 0;
    pos.w = 1;
    return pos;
}

Koordinat ruang klip

Mirip dengan koordinat Tekstur, koordinat ruang klip (juga dikenal sebagai koordinat ruang pasca proyeksi) berbeda antara platform Direct3D-like dan OpenGL-like:

  • Direct3D-like: Kedalaman ruang klip dari +1.0 di pesawat dekat ke 0,0 di pesawat jauh. Ini berlaku untuk Direct3D, Logam dan konsol.

  • OpenGL-like: Kedalaman ruang klip dari –1.0 di pesawat dekat ke +1.0 di pesawat jauh. Ini berlaku untuk OpenGL dan OpenGL ES.

Di dalam kode Shader, Anda dapat menggunakan UNITY_NEAR_CLIP_VALUE makro built-in untuk mendapatkan nilai pesawat dekat berdasarkan platform.

Di dalam kode skrip, gunakan GL.GetGPUProjectionMatrix untuk mengkonversi dari sistem koordinat Unity (yang mengikuti Konvensi OpenGL-like) ke koordinat langsung3D-seperti jika itu adalah apa yang diharapkan platform.

Presisi komputasi Shader

Untuk menghindari masalah presisi, pastikan Anda menguji Shaders Anda di platform target. GPU di perangkat seluler dan PC berbeda dalam bagaimana mereka memperlakukan jenis titik mengambang. PC GPU memperlakukan semua jenis titik mengambang (float, setengah dan tetap) sama - mereka melakukan semua perhitungan menggunakan presisi 32-bit penuh, sementara banyak perangkat seluler GPU tidak melakukan ini.

Lihat dokumentasi tentang jenis data dan presisi untuk rincian.

deklarasi Const di Shaders

Penggunaan const berbeda antara Microsoft HSL (lihat msdn.microsoft.com) dan GLSL OpenGL (lihat Wikipedia) Bahasa Shader.

  • HLSL const Microsoft memiliki banyak makna yang sama seperti yang dilakukan di C# dan C++ dalam variabel yang dinyatakan read-only dalam lingkupnya tetapi dapat diinisialisasikan dengan cara apa pun.

  • OpenGL's GLSL const berarti bahwa variabel secara efektif adalah waktu kompilasi konstan, dan itu harus diinisialisasi dengan mengkompilasi batasan waktu (baik nilai literal atau perhitungan pada consts lainnya).

Yang terbaik adalah mengikuti semantik GLSL OpenGL dan hanya menyatakan variabel sebagai const ketika benar-benar invariant. Hindari menginisialisasi variabel const dengan beberapa nilai mutableAnda dapat mengubah isi paket mutable. Ini adalah kebalikan dari immutable. Hanya Local packages dan Embedded packages mutable.
Lihat di Glossary
lainnya (misalnya, sebagai variabel lokal dalam fungsi). Ini juga bekerja di HLSL Microsoft, sehingga menggunakan const dengan cara ini menghindari kesalahan membingungkan pada beberapa platform.

Semantik yang digunakan oleh Shaders

Untuk mendapatkan Shaders bekerja di semua platform, beberapa nilai Shader harus menggunakan semantik ini:

  • Vertex Shader output (clip space) position: SV_POSITION. Terkadang Shaders menggunakan semantik POSITION untuk mendapatkan Shaders bekerja di semua platform. Perhatikan bahwa ini tidak berfungsi pada Sony PS4 atau dengan tesselasi.

  • Fragment Shader output color: SV_Target. Terkadang Shaders menggunakan COLOR atau COLOR0 untuk mendapatkan Shaders bekerja pada semua platform. Perhatikan bahwa ini tidak berfungsi pada Sony PS4.

Ketika rendering Meshes sebagai Poin, output PSIZE semantik dari simpul (misalnya, set ke 1). Beberapa platform, seperti OpenGL ES atau Metal, memperlakukan ukuran titik sebagai “tidak ditentukan” ketika tidak ditulis dari Shader.

Lihat dokumentasi tentang Shader semantics untuk rincian lebih lanjut.

Login Sitemap

Login Platform D menggunakan Login Catalog Microsoft. compiler HLSL lebih ketat daripada kompiler lain tentang berbagai kesalahan Shader halus. Misalnya, tidak menerima nilai output fungsi yang tidak diinisialisasi dengan benar.

Situasi yang paling umum yang mungkin Anda jalankan menggunakan ini adalah:

  • Pengubah vertex Permukaan ShaderCara merampingkan naungan menulis untuk Pipeline Render Built-in. More info
    Lihat di Glossary
    yang memiliki parameter out. Memastikan output seperti ini:
  void vert (inout appdata_full v, out Input o) 
      {
        **UNITY_INITIALIZE_OUTPUT(Input,o);**
        // ...
      }
  • Nilai awal yang sebagian. Misalnya, fungsi kembali float4 tetapi kode hanya menetapkan nilai .xyz dari itu. Mengatur semua nilai atau perubahan ke float3 jika Anda hanya membutuhkan tiga nilai.

  • Menggunakan tex2D di Vertex Shader. Ini tidak valid, karena turunan UV tidak ada di Shader simpul. Anda perlu sampel tingkat mip eksplisit bukan; misalnya, gunakan tex2Dlod (tex, float4(uv,0,0)). Anda juga perlu menambahkan #pragma target 3.0 sebagai tex2Dlod adalah fitur Shader model 3.0.

DirectX 11 (DX11) HLSL sintaks di Shaders

Beberapa bagian dari pipa kompilasi Permukaan Shader tidak mengerti DirectX 11-specific HLSL (bahasa naungan Microsoft) sintaks.

Jika Anda menggunakan fitur HLSL seperti StructuredBuffers, RWTextures dan sintaksis non-DirectX 9 lainnya, bungkusnya di DirectX X11-only preprocessor macro seperti yang ditunjukkan dalam contoh di bawah ini.

#ifdef SHADER_API_D3D11
// DirectX11-specific code, for example
StructuredBuffer<float4> myColors;
RWTexture2D<float4> myRandomWriteTexture;
#endif

Menggunakan janji shaderbuffer

Beberapa GPU (yang paling terkenal dengan PowerVR di iOS) memungkinkan Anda untuk melakukan bentuk campuran yang dapat diprogram dengan menyediakan warna fragmen saat ini sebagai masukan ke Shader Fragment (lihat EXT_shader_framebuffer_fetch pada khronos.org).

Hal ini dimungkinkan untuk menulis Shaders di Unity yang menggunakan fungsi pengambilan bingkaibuffer. Untuk melakukan ini, gunakan argumen warna inout ketika Anda menulis Shader Fragment dalam bahasa HLSL (bahasa pencukur Microsoft - lihat msdn.microsoft.com) atau Cg (bahasa yang dicukur oleh Nvidia - lihat nvidia.co.uk).

Contoh di bawah ini dalam Cg.

CGPROGRAM
// only compile Shader for platforms that can potentially
// do it (currently gles,gles3,metal)
#pragma only_renderers framebufferfetch

void frag (v2f i, inout half4 ocol : SV_Target)
{
    // ocol can be read (current framebuffer color)
    // and written into (will change color to that one)
    // ...
}   
ENDCG

Kedalaman (Z) arah di Shaders

Arah kedalaman (Z) berbeda pada platform Shader yang berbeda.

DirectX 11, DirectX 12, Metal: Reversed direction

  • Penyangga kedalaman (Z) adalah 1,0 di pesawat dekat, menurun menjadi 0,0 di pesawat jauh.

  • Rentang ruang klip adalah [dekat,0] (meskipun jarak dekat pesawat di dekat pesawat, menurun menjadi 0,0 di pesawat jauh).

Other platforms: Traditional direction

  • Nilai penyangga kedalaman (Z) adalah 0,0 di pesawat dekat dan 1.0 di pesawat jauh.

  • Ruang klip tergantung pada platform tertentu:
    • Di platform langsung3D-like, kisarannya adalah [0,far] (meaning 0,0 di pesawat dekat, meningkatkan jarak pesawat jauh di pesawat jauh).
    • Pada platform OpenGL-like, kisarannya adalah [kurang, jauh] (meaning minus jarak dekat pesawat di dekat pesawat, meningkatkan jarak pesawat jauh di pesawat jauh).

Perhatikan bahwa kedalaman arah terbalik (Z), dikombinasikan dengan titik mengambang depth bufferSebuah toko memori yang memegang kedalaman nilai z setiap pixel dalam gambar, di mana nilai z adalah kedalaman untuk setiap piksel yang diberikan dari pesawat proyeksi. More info
Lihat di Glossary
, secara signifikan meningkatkan presisi penyangga kedalaman terhadap arah tradisional. Keuntungan dari ini adalah kurang konflik untuk koordinat Z dan bayangan yang lebih baik, terutama ketika menggunakan pesawat dekat kecil dan pesawat jauh besar.

Jadi, ketika Anda menggunakan Shaders dari platform dengan kedalaman (Z) terbalik:

  • UNITY_REVERSED_Z didefinisikan.
  • Sitemap Rentang tekstur tekstur tekstur adalah 1 (dekat) hingga 0 (jauh)._CameraDepth Texture texture range is 1 (near) to 0 (far).
  • Rentang ruang klip adalah dalam "dekat" (dekat) ke 0 (jauh).

Namun, makro dan fungsi berikut secara otomatis melakukan perbedaan dalam arah (Z):

  • Linear01Depth(float z)
  • LinearEyeDepth(float z)
  • UNITY_CALC_FOG_FACTOR(koord)

Mencapai Buffer kedalaman

Jika Anda mengambil nilai buffer kedalaman (Z) secara manual, Anda mungkin ingin memeriksa arah penyangga. Berikut ini adalah contoh dari ini:

float z = tex2D(_CameraDepthTexture, uv);
#if defined(UNITY_REVERSED_Z)
    z = 1.0f - z;
#endif

Menggunakan ruang klip

Jika Anda menggunakan ruang klip (Z) secara manual, Anda mungkin juga ingin perbedaan platform abstrak dengan menggunakan makro berikut:

float clipSpaceRange01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(rawClipSpace);

Note: Makro ini tidak mengubah ruang klip di platform OpenGL atau OpenGL ES, sehingga kembali dalam "near"1 (near) sejauh ini (far) di platform ini.

Projection matrices

GL.GetGPUProjectionMatrix() mengembalikan matriks z-reverted jika Anda berada di platform di mana kedalaman (Z) terbalik. Namun, jika Anda bersaing dari matriks proyeksi secara manual (misalnya, untuk bayangan kustom atau rendering kedalaman), Anda perlu mengalihkan kedalaman (Z) arahkan diri Anda di mana itu berlaku melalui script.

Contoh ini di bawah ini:

var shadowProjection = Matrix4x4.Ortho(...); //shadow camera projection matrix
var shadowViewMat = ...     //shadow camera view matrix
var shadowSpaceMatrix = ... //from clip to shadowMap texture space
    
//'m_shadowCamera.projectionMatrix' is implicitly reversed 
//when the engine calculates device projection matrix from the camera projection
m_shadowCamera.projectionMatrix = shadowProjection; 

//'shadowProjection' is manually flipped before being concatenated to 'm_shadowMatrix'
//because it is seen as any other matrix to a Shader.
if(SystemInfo.usesReversedZBuffer) 
{
    shadowProjection[2, 0] = -shadowProjection[2, 0];
    shadowProjection[2, 1] = -shadowProjection[2, 1];
    shadowProjection[2, 2] = -shadowProjection[2, 2];
    shadowProjection[2, 3] = -shadowProjection[2, 3];
}
    m_shadowMatrix = shadowSpaceMatrix * shadowProjection * shadowViewMat;

Kedalaman (Z) bias

Unity secara otomatis berurusan dengan bias kedalaman (Z) untuk memastikannya cocok dengan arah kedalaman Unity (Z). Namun, jika Anda menggunakan plugin rendering kode asli, Anda perlu mengabaikan kedalaman (kebalikan) (Z) bias dalam kode C++ Anda.

Alat untuk memeriksa arah kedalaman (Z)

Permukaan Shader dengan DX11 / OpenGL Inti Tesselasi
Memahami kinerja naungan