首頁 web前端 js教程 網路上的三角形 抓取一些東西

網路上的三角形 抓取一些東西

Nov 30, 2024 am 02:42 AM

本系列介紹 WebGPU 與一般電腦圖形學。

首先讓我們看看我們要建造什麼,

生命遊戲

Triangles On Web Chraw Something

3D 渲染

Triangles On Web Chraw Something

3D 渲染,但有燈光

Triangles On Web Chraw Something

渲染 3D 模型

Triangles On Web Chraw Something

除了JS基礎知識外,不需要任何基礎知識。

教學已經在我的 github 上完成,附有原始碼。

WebGPU 是一個相對較新的 GPU API。儘管名為 WebGPU,但它實際上可以被視為 Vulkan、DirectX 12、Metal、OpenGL 和 WebGL 之上的一層。它被設計為低階 API,旨在用於高效能應用程序,例如遊戲和模擬。

在本章中,我們將在螢幕上繪製一些東西。第一部分將參考 Google Codelabs 教學。我們將在螢幕上創建一個生活遊戲。

起點

我們將在啟用 typescript 的 vite 中建立一個空的普通 JS 專案。然後清除所有多餘的程式碼,只留下main.ts。

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

main()
登入後複製
登入後複製
登入後複製
登入後複製

在實際編碼之前,請檢查您的瀏覽器是否啟用了 WebGPU。您可以在 WebGPU Samples 上查看它。

Chrome 現在預設為啟用狀態。在 Safari 上,您應該前往開發者設定、標記設定並啟用 WebGPU。

我們還需要為 WebGPU 啟用這些類型,安裝 @webgpu/types,並在 tsc 編譯器選項中加入 "types": ["@webgpu/types"]。

此外,我們替換了

畫一個三角形

WebGPU 有許多樣板程式碼,如下圖所示。

請求設備

首先我們需要存取 GPU。在WebGPU中,是透過適配器的概念來完成的,適配器是GPU和瀏覽器之間的橋樑。

const adapter = await navigator.gpu.requestAdapter();
登入後複製
登入後複製
登入後複製
登入後複製

然後我們需要向適配器請求一個設備。

const device = await adapter.requestDevice();
console.log(device);
登入後複製
登入後複製
登入後複製
登入後複製

配置畫布

我們在畫布上繪製三角形。我們需要取得canvas元素並配置它。

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

這裡,我們使用 getContext 來取得畫布的相關資訊。透過指定 webgpu,我們將獲得一個負責使用 WebGPU 進行渲染的上下文。

CanvasFormat其實就是顏色模式,例如srgb。我們通常只使用首選格式。

最後,我們使用設備和格式來配置上下文。

了解 GPU 渲染管線

在深入研究工程細節之前,我們首先必須了解 GPU 如何處理渲染。

GPU 渲染管道是 GPU 渲染影像所採取的一系列步驟。

在 GPU 上執行的應用程式稱為著色器。著色器是運行在GPU上的程式。著色器有一種特殊的程式語言,我們稍後會討論。

渲染管有以下步驟,

  1. CPU 將資料載入到 GPU 中。 CPU可能會移除一些不可見的物體以節省GPU資源。
  2. CPU 設定 GPU 渲染場景所需的所有顏色、紋理和其他資料。
  3. CPU 觸發對 GPU 的繪製呼叫。
  4. GPU從CPU取得資料並開始渲染場景。
  5. GPU 運行到幾何進程,該進程處理場景的頂點。
  6. 在幾何過程中,第一步是頂點著色器,它處理場景的頂點。它可能會變換頂點,改變頂點的顏色,或對頂點做其他事情。
  7. 下一步是曲面細分著色器,它處理場景的頂點。它對頂點進行細分,其目的是增加場景的細節。它的程序也很多,但是太複雜了,無法在這裡解釋。
  8. 下一步是幾何著色器,它處理場景的頂點。與頂點著色器相比,開發人員只能定義如何變換一個頂點,而幾何著色器可以定義如何變換多個頂點。它還可以創建新的頂點,新的頂點可用於建立新的幾何體。
  9. 幾何處理的最後一步包括裁剪,去除超出螢幕的多餘部分,以及剔除,去除相機不可見的不可見部分。
  10. 下一步是光柵化過程,將頂點轉換為片段。片段是將要在螢幕上渲染的像素。
  11. 下一步是三角形迭代,即迭代場景的三角形。
  12. 下一步是片段著色器,它處理場景的片段。它可能會改變片段的顏色,改變片段的紋理,或對片段做其他事情。在這一部分中,還進行了深度測試和模板測試。深度測試是指為每個片段賦予深度值,深度值最小的片段將被渲染。 Stencil測試是指為每個fragment賦予stencil值,透過stencil測試的fragment將被渲染。模板值由開發者決定。
  13. 下一步是混合過程,混合場景的片段。例如,如果兩個片段重疊,則混合過程會將兩個片段混合在一起。
  14. 最後一步是輸出過程,將碎片輸出到交換鏈。交換鍊是用於渲染場景的影像鏈。更簡單地說,它是一個緩衝區,用於保存將要在螢幕上顯示的圖像。

根據圖元(GPU 可以渲染的最小單位)的不同,管道可能有不同的步驟。通常,我們使用三角形,它通知 GPU 將每 3 組頂點視為三角形。

建立渲染通道

Render Pass 是完整 GPU 渲染的一個步驟。建立渲染頻道後,GPU 將開始渲染場景,完成後反之亦然。

要建立渲染通道,我們需要建立一個編碼器,負責將渲染通道編譯為 GPU 程式碼。

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

main()
登入後複製
登入後複製
登入後複製
登入後複製

然後我們建立一個渲染通道。

const adapter = await navigator.gpu.requestAdapter();
登入後複製
登入後複製
登入後複製
登入後複製

在這裡,我們建立一個帶有顏色附件的渲染通道。附件是 GPU 中的一個概念,表示將要渲染的影像。一張圖像可能有很多個方面需要 GPU 處理,每個方面都是一個附件。

這裡我們只有一個配件,就是顏色配件。視圖是 GPU 將在其上渲染的面板,這裡我們將其設定為畫布的紋理。

loadOp是GPU在渲染通道之前執行的操作,clear表示GPU將首先清除最後一幀之前的所有數據,storeOp是GPU在渲染通道之後執行的操作,store表示GPU將把數據儲存到紋理中。

loadOp可以是load,它保留最後一幀的數據,也可以是clear,它清除最後一幀的數據。 storeOp可以是store,資料儲存到紋理,也可以是discard,丟棄資料。

現在,只需呼叫 pass.end() 即可結束渲染通道。現在,該命令已保存在 GPU 的命令緩衝區中。

要取得編譯後的指令,請使用以下程式碼,

const device = await adapter.requestDevice();
console.log(device);
登入後複製
登入後複製
登入後複製
登入後複製

最後,將指令提交到 GPU 的渲染佇列。

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

現在,您應該會看到一個醜陋的黑色畫布。

根據我們對 3D 的刻板印象,我們期望空白空間是藍色的。我們可以透過設定透明顏色來做到這一點。

const encoder = device.createCommandEncoder();
登入後複製

使用著色器繪製三角形

現在,我們將在畫布上繪製一個三角形。我們將使用著色器來做到這一點。著色器語言將是 wgsl,WebGPU 著色語言。

現在,假設我們要繪製一個具有以下座標的三角形,

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

正如我們之前所說,要完成渲染管道,我們需要一個頂點著色器和一個片段著色器。

頂點著色器

使用以下程式碼建立著色器模組。

const commandBuffer = encoder.finish();
登入後複製

這裡的label只是一個名稱,用來除錯。 code 是實際的著色器代碼。

頂點著色器是一個接受任意參數並傳回頂點位置的函數。然而,與我們的預期相反,頂點著色器會傳回一個四維向量,而不是一個三維向量。第四個維度是w維度,用於透視劃分。我們稍後再討論。

現在,您可以簡單地將四維向量 (x, y, z, w) 視為三維向量 (x / w, y / w, z / w)。

但是,還有一個問題-如何將資料傳遞給著色器,以及如何從著色器中取出資料。

為了將資料傳遞給著色器,我們使用 vertexBuffer,一個包含頂點資料的緩衝區。我們可以使用以下程式碼建立一個緩衝區,

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

main()
登入後複製
登入後複製
登入後複製
登入後複製

這裡我們建立了一個緩衝區,大小是24位元組,6個浮點數,這是頂點的大小。

usage是緩衝區的使用情況,對於頂點資料來說就是VERTEX。 GPUBufferUsage.COPY_DST 表示該緩衝區可作為複製目標。對於所有由CPU寫入資料的緩衝區,我們需要設定這個標誌。

這裡的map是指將buffer映射到CPU,也就是說CPU可以對buffer進行讀寫操作。 unmap的意思是取消緩衝區的映射,這表示CPU不能再讀寫緩衝區,因此內容可供GPU使用。

現在,我們可以將資料寫入緩衝區。

const adapter = await navigator.gpu.requestAdapter();
登入後複製
登入後複製
登入後複製
登入後複製

這裡,我們將緩衝區映射到CPU,並將資料寫入緩衝區。然後我們取消映射緩衝區。

vertexBuffer.getMappedRange() 將會傳回對應到 CPU 的緩衝區範圍。我們可以用它來將資料寫入緩衝區。

但是,這些只是原始數據,GPU 不知道如何解釋它們。我們需要定義緩衝區的佈局。

const device = await adapter.requestDevice();
console.log(device);
登入後複製
登入後複製
登入後複製
登入後複製

在這裡,arrayStride是GPU在尋找下一個輸入時需要在緩衝區中向前跳過的位元組數。例如,如果 arrayStride 為 8,GPU 將跳過 8 個位元組來取得下一個輸入。

由於這裡我們使用float32x2,步幅是8個位元組,每個float 4個位元組,每個頂點2個float。

現在我們可以寫頂點著色器了。

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

這裡,@vertex 表示這是一個頂點著色器。 @location(0) 表示屬性的位置,如前面定義的那樣,為 0。請注意,在著色器語言中,您正在處理緩衝區的佈局,因此每當您傳遞一個值時,您需要傳遞一個結構體,其欄位已定義@location,或僅傳遞一個帶有@location的值。

vec2f 是二維浮點向量,vec4f 是四維浮點向量。由於頂點著色器需要傳回 vec4f 位置,因此我們需要使用 @builtin(position) 對其進行註解。

片段著色器

片段著色器,類似地,是取得插值頂點輸出並輸出附件(在本例中為顏色)的東西。插值意味著雖然只有頂點上的某些像素具有確定的值,但對於每隔一個像素,這些值都會被插值,可以是線性的、平均的或其他方式。 fragment的顏色是一個四維向量,即fragment的顏色,分別是紅、綠、藍、alpha。

請注意,顏色的範圍是0到1,而不是0到255。此外,片段著色器定義的是每個頂點的顏色,而不是三角形的顏色。三角形的顏色由頂點的顏色透過內插法決定。

由於我們目前不想控製片段的顏色,所以我們可以簡單地回傳一個常數顏色。

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

main()
登入後複製
登入後複製
登入後複製
登入後複製

渲染管線

然後我們透過取代頂點和片段著色器來定義自訂渲染管道。

const adapter = await navigator.gpu.requestAdapter();
登入後複製
登入後複製
登入後複製
登入後複製

注意,在片段著色器中,我們需要指定目標的格式,也就是畫布的格式。

抽獎

在渲染過程結束之前,我們先加入繪製呼叫。

const device = await adapter.requestDevice();
console.log(device);
登入後複製
登入後複製
登入後複製
登入後複製

這裡,在setVertexBuffer中,第一個參數是緩衝區的索引,在管道定義欄位buffers中,第二個參數是緩衝區本身。

呼叫draw時,參數是要繪製的頂點數。由於我們有 3 個頂點,因此我們繪製 3 個。

現在,您應該在畫布上看到一個黃色三角形。

繪製生命遊戲細胞

現在我們稍微調整一下程式碼 - 因為我們想要建立一個生活遊戲,所以我們需要繪製正方形而不是三角形。

正方形其實是兩個三角形,所以我們要畫6個頂點。這裡的改動很簡單,不需要詳細解釋。

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

現在,您應該在畫布上看到一個黃色方塊。

座標系

我們沒有討論GPU的座標系。嗯,這相當簡單。 GPU實際的座標係是右手座標系,即x軸指向右側,y軸指向上方,z軸指向螢幕外。

座標系的範圍是-1到1。原點位於螢幕中心。 z軸從0到1,0是近平面,1是遠平面。然而,z 軸代表深度。當你做3D渲染時,你不能只使用z軸來決定物體的位置,你需要使用透視劃分。這稱為 NDC,標準化設備座標。

例如,要在螢幕左上角畫一個正方形,頂點為(-1, 1), (-1, 0), (0, 1), (0, 0) ,儘管你需要使用兩個三角形來繪製它。

以上是網路上的三角形 抓取一些東西的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1657
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles