Rumah >hujung hadapan web >tutorial js >Segitiga Pada Web Chraw Sesuatu

Segitiga Pada Web Chraw Sesuatu

Patricia Arquette
Patricia Arquetteasal
2024-11-30 02:42:10162semak imbas

Siri ini memperkenalkan WebGPU dan grafik komputer secara umum.

Mula-mula mari kita lihat apa yang akan kita bina,

Permainan Kehidupan

Triangles On Web Chraw Something

Pemarahan 3D

Triangles On Web Chraw Something

Pemarahan 3D, tetapi dengan pencahayaan

Triangles On Web Chraw Something

Memaparkan Model 3D

Triangles On Web Chraw Something

Kecuali pengetahuan asas JS, tiada pengetahuan awal diperlukan.

Tutorial sudah selesai di github saya, bersama-sama dengan kod sumber.

WebGPU ialah API yang agak baharu untuk GPU. Walaupun dinamakan sebagai WebGPU, ia sebenarnya boleh dianggap sebagai lapisan di atas Vulkan, DirectX 12, dan Metal, OpenGL dan WebGL. Ia direka bentuk untuk menjadi API peringkat rendah dan bertujuan untuk digunakan untuk aplikasi berprestasi tinggi, seperti permainan dan simulasi.

Dalam bab ini, kita akan melukis sesuatu pada skrin. Bahagian pertama akan merujuk kepada Tutorial Google Codelabs. Kami akan mencipta permainan hidup pada skrin.

Titik Permulaan

Kami hanya akan mencipta projek JS vanila kosong secara invite dengan skrip taip didayakan. Kemudian kosongkan semua kod tambahan, hanya tinggalkan main.ts.

const main = async () => {
    console.log('Hello, world!')
}

main()

Sebelum pengekodan sebenar, sila semak sama ada penyemak imbas anda telah mendayakan WebGPU. Anda boleh menyemaknya pada Sampel WebGPU.

Chrome kini lalai kepada didayakan. Pada Safari, anda harus pergi ke tetapan pembangun, tetapan bendera dan dayakan WebGPU.

Kami juga perlu mendayakan jenis anda untuk WebGPU, memasang @webgpu/types dan dalam pilihan pengkompil tsc, tambah "jenis": ["@webgpu/types"].

Selain itu, kami menggantikan

Melukis Segi Tiga

Terdapat banyak kod boilerplate ke WebGPU, begini rupanya.

Meminta Peranti

Mula-mula kita memerlukan akses kepada GPU. Dalam WebGPU, ia dilakukan dengan konsep penyesuai, yang merupakan jambatan antara GPU dan penyemak imbas.

const adapter = await navigator.gpu.requestAdapter();

Kemudian kita perlu meminta peranti daripada penyesuai.

const device = await adapter.requestDevice();
console.log(device);

Konfigurasikan Kanvas

Kami melukis segitiga kami pada kanvas. Kita perlu mendapatkan elemen kanvas dan mengkonfigurasinya.

const canvas = document.getElementById('app') as HTMLCanvasElement;
const context = canvas.getContext("webgpu")!;
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
    device: device,
    format: canvasFormat,
});

Di sini, kami menggunakan getContext untuk mendapatkan maklumat relatif tentang kanvas. Dengan menentukan webgpu, kami akan mendapat konteks yang bertanggungjawab untuk membuat dengan WebGPU.

CanvasFormat sebenarnya ialah mod warna, contohnya, srgb. Kami biasanya hanya menggunakan format pilihan.

Akhir sekali, kami mengkonfigurasi konteks dengan peranti dan format.

Memahami GPU Rendering Pipeline

Sebelum menyelami lebih lanjut butiran kejuruteraan, kita mesti memahami cara GPU mengendalikan pemaparan.

Saluran paip pemaparan GPU ialah satu siri langkah yang diambil oleh GPU untuk memaparkan imej.

Aplikasi yang dijalankan pada GPU dipanggil shader. Shader ialah program yang dijalankan pada GPU. Shader mempunyai bahasa pengaturcaraan khas yang akan kita bincangkan kemudian.

Saluran paip render mempunyai langkah berikut,

  1. CPU memuatkan data ke dalam GPU. CPU mungkin mengalih keluar beberapa objek halimunan untuk menyimpan sumber GPU.
  2. CPU menetapkan semua warna, tekstur dan data lain yang GPU perlukan untuk memaparkan pemandangan.
  3. CPU mencetuskan panggilan seri kepada GPU.
  4. GPU mendapat data daripada CPU dan mula memaparkan pemandangan.
  5. GPU memasuki proses geometri, yang memproses bucu tempat kejadian.
  6. Dalam proses geometri, langkah pertama ialah pelorek bucu, yang memproses bucu tempat kejadian. Ia mungkin mengubah bucu, menukar warna bucu atau melakukan perkara lain pada bucu.
  7. Langkah seterusnya ialah pelorek teselasi, yang memproses bucu tempat kejadian. Ia melakukan pembahagian bucu, yang tujuannya adalah untuk meningkatkan perincian tempat kejadian. Ia juga mempunyai banyak prosedur tetapi ia terlalu rumit untuk dijelaskan di sini.
  8. Langkah seterusnya ialah pelorek geometri, yang memproses bucu tempat kejadian. Berbeza dengan pelorek puncak, di mana pembangun hanya boleh menentukan cara satu bucu diubah, pelorek geometri boleh menentukan cara berbilang bucu diubah. Ia juga boleh mencipta bucu baharu, yang boleh digunakan untuk mencipta geometri baharu.
  9. Langkah terakhir proses geometri mengandungi keratan, mengalih keluar bahagian yang tidak wajar yang melebihi skrin dan memusnahkan, mengalihkan bahagian halimunan yang tidak kelihatan kepada kamera.
  10. Langkah seterusnya ialah proses rasterisasi, yang menukar bucu kepada serpihan. Serpihan ialah piksel yang akan dipaparkan pada skrin.
  11. Langkah seterusnya ialah lelaran segi tiga, yang berulang ke atas segi tiga tempat kejadian.
  12. Langkah seterusnya ialah pelorek serpihan, yang memproses serpihan tempat kejadian. Ia mungkin menukar warna serpihan, menukar tekstur serpihan atau melakukan perkara lain pada serpihan. Dalam bahagian ini, ujian kedalaman dan ujian stensil juga dilakukan. Ujian kedalaman bermaksud untuk memberikan setiap serpihan dengan nilai kedalaman, dan serpihan dengan nilai kedalaman terkecil akan diberikan. Ujian stensil bermaksud untuk memberikan setiap serpihan dengan nilai stensil, dan serpihan yang lulus ujian stensil akan diberikan. Nilai stensil ditentukan oleh pembangun.
  13. Langkah seterusnya ialah proses pengadunan, yang menggabungkan serpihan adegan. Contohnya, jika dua serpihan bertindih, proses pengadunan akan menggabungkan kedua-dua serpihan itu bersama-sama.
  14. Langkah terakhir ialah proses output, yang mengeluarkan serpihan ke rantai swap. Rantaian swap ialah rangkaian imej yang digunakan untuk memaparkan pemandangan. Secara ringkasnya, ia adalah penimbal yang menyimpan imej yang akan dipaparkan pada skrin.

Bergantung pada primitif, unit terkecil yang boleh dihasilkan oleh GPU, saluran paip mungkin mempunyai langkah yang berbeza. Biasanya, kami menggunakan segi tiga, yang memberi isyarat kepada GPU untuk menganggap setiap 3 kumpulan bucu sebagai segi tiga.

Mencipta Pas Render

Render Pass ialah satu langkah pemaparan GPU penuh. Apabila pas render dibuat, GPU akan mula memaparkan pemandangan, dan begitu juga sebaliknya apabila ia selesai.

Untuk membuat pas render, kami perlu mencipta pengekod yang bertanggungjawab untuk menyusun pas render kepada kod GPU.

const main = async () => {
    console.log('Hello, world!')
}

main()




Kemudian kami mencipta pas render.

const adapter = await navigator.gpu.requestAdapter();

Di sini, kami mencipta pas render dengan lampiran warna. Lampiran ialah konsep dalam GPU yang mewakili imej yang akan dipaparkan. Imej mungkin mempunyai banyak aspek yang perlu diproses oleh GPU, dan setiap satu daripadanya ialah lampiran.

Di sini kami hanya mempunyai satu lampiran, iaitu lampiran warna. Pandangan ialah panel yang akan dipaparkan oleh GPU, di sini kami menetapkannya kepada tekstur kanvas.

loadOp ialah operasi yang GPU akan lakukan sebelum pas render, clear bermaksud GPU akan mengosongkan semua data sebelum ini daripada bingkai terakhir, dan storeOp ialah operasi yang GPU akan lakukan selepas pas render, store bermaksud GPU akan menyimpan data kepada tekstur.

loadOp boleh memuatkan, yang mengekalkan data daripada bingkai terakhir, atau mengosongkan, yang mengosongkan data daripada bingkai terakhir. storeOp boleh menyimpan, yang menyimpan data kepada tekstur, atau membuang, yang membuang data.

Sekarang, cuma panggil pass.end() untuk menamatkan pas render. Kini, arahan itu disimpan dalam penimbal perintah GPU.

Untuk mendapatkan arahan yang disusun, gunakan kod berikut,

const device = await adapter.requestDevice();
console.log(device);

Dan, akhirnya, serahkan arahan kepada baris gilir pemaparan GPU.

const canvas = document.getElementById('app') as HTMLCanvasElement;
const context = canvas.getContext("webgpu")!;
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
    device: device,
    format: canvasFormat,
});

Sekarang, anda sepatutnya melihat kanvas hitam yang hodoh.

Berdasarkan konsep stereotaip kami tentang 3D, kami menjangkakan ruang kosong menjadi warna biru. Kita boleh melakukannya dengan menetapkan warna yang jelas.

const encoder = device.createCommandEncoder();

Melukis Segi Tiga Menggunakan Shader

Sekarang, kita akan melukis segitiga pada kanvas. Kami akan menggunakan shader untuk melakukannya. Bahasa shader ialah wgsl, WebGPU Shading Language.

Sekarang, andaikan kita ingin melukis segitiga dengan koordinat berikut,

const pass = encoder.beginRenderPass({
  colorAttachments: [{
     view: context.getCurrentTexture().createView(),
     loadOp: "clear",
     storeOp: "store",
  }]
});

Seperti yang kami nyatakan sebelum ini, untuk melengkapkan saluran paip pemaparan, kami memerlukan pelorek puncak dan pelorek serpihan.

Vertex Shader

Gunakan kod berikut untuk mencipta modul shader.

const commandBuffer = encoder.finish();

label di sini hanyalah nama, yang dimaksudkan untuk nyahpepijat. kod ialah kod shader sebenar.

Penedar bucu ialah fungsi yang mengambil sebarang parameter dan mengembalikan kedudukan bucu. Walau bagaimanapun, bertentangan dengan apa yang kita jangkakan, pelorek puncak mengembalikan vektor empat dimensi, bukan vektor tiga dimensi. Dimensi keempat ialah dimensi w, yang digunakan untuk pembahagian perspektif. Kami akan membincangkannya kemudian.

Kini, anda boleh menganggap vektor empat dimensi (x, y, z, w) sebagai vektor tiga dimensi (x / w, y / w, z / w).

Walau bagaimanapun, terdapat satu lagi masalah- cara menghantar data kepada pelorek, dan cara mengeluarkan data daripada pelorek.

Untuk menghantar data kepada shader, kami menggunakan vertexBuffer, penimbal yang mengandungi data bucu. Kita boleh membuat penimbal dengan kod berikut,

const main = async () => {
    console.log('Hello, world!')
}

main()

Di sini kami mencipta penimbal dengan saiz 24 bait, 6 terapung, iaitu saiz bucu.

penggunaan ialah penggunaan penimbal, iaitu VERTEX untuk data bucu. GPUBufferUsage.COPY_DST bermakna penimbal ini sah sebagai destinasi salinan. Untuk semua penimbal yang datanya ditulis oleh CPU, kami perlu menetapkan bendera ini.

Peta di sini bermaksud memetakan penimbal kepada CPU, yang bermaksud CPU boleh membaca dan menulis penimbal. Nyahpeta bermaksud menyahpeta penimbal, yang bermaksud CPU tidak lagi boleh membaca dan menulis penimbal, dan dengan itu kandungan tersedia kepada GPU.

Kini, kita boleh menulis data pada penimbal.

const adapter = await navigator.gpu.requestAdapter();

Di sini, kami memetakan penimbal ke CPU dan menulis data ke penimbal. Kemudian kami nyahpetakan penimbal.

vertexBuffer.getMappedRange() akan mengembalikan julat penimbal yang dipetakan ke CPU. Kita boleh menggunakannya untuk menulis data ke penimbal.

Walau bagaimanapun, ini hanyalah data mentah dan GPU tidak tahu cara mentafsirnya. Kita perlu menentukan reka letak penimbal.

const device = await adapter.requestDevice();
console.log(device);

Di sini, arrayStride ialah bilangan bait yang diperlukan oleh GPU untuk melangkau ke hadapan dalam penimbal apabila ia mencari input seterusnya. Contohnya, jika arrayStride ialah 8, GPU akan melangkau 8 bait untuk mendapatkan input seterusnya.

Sejak di sini, kami menggunakan float32x2, langkahnya ialah 8 bait, 4 bait untuk setiap apungan dan 2 apungan untuk setiap bucu.

Kini kita boleh menulis pelorek puncak.

const canvas = document.getElementById('app') as HTMLCanvasElement;
const context = canvas.getContext("webgpu")!;
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
    device: device,
    format: canvasFormat,
});

Di sini, @vertex bermaksud ini ialah pelorek puncak. @location(0) bermaksud lokasi atribut, iaitu 0, seperti yang ditakrifkan sebelum ini. Sila ambil perhatian bahawa dalam bahasa shader, anda berurusan dengan reka letak penimbal, jadi apabila anda lulus nilai, anda perlu lulus sama ada struct, yang medannya telah mentakrifkan @lokasi atau hanya nilai dengan @lokasi.

vec2f ialah vektor apungan dua dimensi dan vec4f ialah vektor apungan empat dimensi. Memandangkan vertex shader diperlukan untuk mengembalikan kedudukan vec4f, kita perlu menganotasikannya dengan @builtin(position).

Pewarna Serpihan

Penetak serpihan, begitu juga, ialah sesuatu yang mengambil output bucu interpolasi dan mengeluarkan lampiran, berwarna dalam kes ini. Interpolasi bermakna bahawa walaupun hanya piksel tertentu pada bucu yang telah menentukan nilai, untuk setiap piksel lain, nilai diinterpolasi, sama ada linear, purata atau cara lain. Warna serpihan ialah vektor empat dimensi, iaitu warna serpihan, masing-masing merah, hijau, biru dan alfa.

Sila ambil perhatian bahawa warna adalah dalam julat 0 hingga 1, bukan 0 hingga 255. Selain itu, peneduh serpihan mentakrifkan warna setiap bucu, bukan warna segi tiga. Warna segi tiga ditentukan oleh warna bucu, dengan interpolasi.

Memandangkan pada masa ini kami tidak peduli untuk mengawal warna serpihan, kami hanya boleh mengembalikan warna tetap.

const main = async () => {
    console.log('Hello, world!')
}

main()

Render Pipeline

Kemudian kami mentakrifkan saluran paip pemaparan tersuai dengan menggantikan puncak dan peneduh serpihan.

const adapter = await navigator.gpu.requestAdapter();

Perhatikan bahawa dalam pelorek serpihan, kita perlu menentukan format sasaran, iaitu format kanvas.

Lukis Panggilan

Sebelum hantar hantaran tamat, kami menambah panggilan cabutan.

const device = await adapter.requestDevice();
console.log(device);

Di sini, dalam setVertexBuffer, parameter pertama ialah indeks penimbal, dalam penampan medan definisi saluran paip dan parameter kedua ialah penimbal itu sendiri.

Apabila memanggil cabutan, parameter ialah bilangan bucu untuk dilukis. Oleh kerana kami mempunyai 3 bucu, kami melukis 3.

Sekarang, anda sepatutnya melihat segi tiga kuning pada kanvas.

Lukis Sel Permainan Kehidupan

Kini kami mengubah suai kod kami sedikit- memandangkan kami ingin membina permainan kehidupan, jadi kami perlu melukis segi empat sama bukannya segi tiga.

Segi empat sama sebenarnya ialah dua segi tiga, jadi kita perlu melukis 6 bucu. Perubahan di sini adalah mudah dan anda tidak memerlukan penjelasan terperinci.

const canvas = document.getElementById('app') as HTMLCanvasElement;
const context = canvas.getContext("webgpu")!;
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
    device: device,
    format: canvasFormat,
});

Sekarang, anda sepatutnya melihat segi empat sama kuning pada kanvas.

Sistem Koordinat

Kami tidak membincangkan sistem koordinat GPU. Ia, baik, agak mudah. Sistem koordinat sebenar GPU ialah sistem koordinat tangan kanan, yang bermaksud paksi-x menghala ke kanan, paksi-y menghala ke atas dan paksi-z menghala keluar dari skrin.

Julat sistem koordinat adalah dari -1 hingga 1. Asal berada di tengah-tengah skrin. paksi z ialah dari 0 hingga 1, 0 ialah satah dekat, dan 1 ialah satah jauh. Walau bagaimanapun, paksi z adalah untuk kedalaman. Apabila anda melakukan rendering 3D, anda tidak boleh hanya menggunakan paksi z untuk menentukan kedudukan objek, anda perlu menggunakan bahagian perspektif. Ini dipanggil NDC, koordinat peranti ternormal.

Contohnya, jika anda ingin melukis segi empat sama di penjuru kiri sebelah atas skrin, bucunya ialah (-1, 1), (-1, 0), (0, 1), (0, 0) , walaupun anda perlu menggunakan dua segi tiga untuk melukisnya.

Atas ialah kandungan terperinci Segitiga Pada Web Chraw Sesuatu. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn