日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Web 端的下一代三维图形

發(fā)布時(shí)間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Web 端的下一代三维图形 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 原文地址:Next-generation 3D Graphics on the Web
  • 原文作者:Dean Jackson
  • 譯文出自:掘金翻譯計(jì)劃
  • 本文永久鏈接:github.com/xitu/gold-m…
  • 譯者:reid3290
  • 校對(duì)者:leviding,H2O-2

今天,蘋果 WebKit 團(tuán)隊(duì)提議在 W3C 成立一個(gè)新的社區(qū)群組(Community Group)來討論 Web 端三維圖形的未來和開發(fā)一款支持現(xiàn)代 GPU 特性(包括底層圖像處理和通用計(jì)算)的標(biāo)準(zhǔn) API。W3C 社區(qū)允許大家自由參與進(jìn)來,而且我們也誠(chéng)邀瀏覽器開發(fā)商、GPU 硬件提供商、軟件開發(fā)者和 Web 社區(qū)加入我們。

權(quán)當(dāng)拋磚引玉,我們分享了一個(gè) API 提案和一個(gè)針對(duì) WebKit 開源項(xiàng)目的 API 原型。我們希望這是一個(gè)有益的開始,并期待隨著社區(qū)討論的進(jìn)行 API 會(huì)不斷發(fā)展進(jìn)化。

更新:現(xiàn)在有一個(gè)實(shí)現(xiàn)和演示 WebGPU 的 demo。

讓我們來看看我們成立這個(gè)社區(qū)群組的前因后果,以及這個(gè)新組與現(xiàn)有 Web 圖形 API(如 WebGL)的關(guān)系。

首先談點(diǎn)歷史問題

有一段時(shí)間,基于 Web 標(biāo)準(zhǔn)的技術(shù)可以生成具有靜態(tài)內(nèi)容的頁面,而其中唯一的圖形則是嵌入的圖片。不久之后,Web 開始增加更多開發(fā)人員可以通過 JavaScript 訪問的功能。最終,我們需要一個(gè)完全可編程的圖形 API,以使腳本可以實(shí)時(shí)創(chuàng)建圖像。因此,“canvas” 元素及其相關(guān)的 2D 渲染 API 誕生于 WebKit,隨后迅速普及到其他瀏覽器引擎中,并且很快標(biāo)準(zhǔn)化了。

隨著時(shí)間的推移,Web 應(yīng)用程序和內(nèi)容漸趨豐富和復(fù)雜,并開始觸及平臺(tái)的瓶頸。以游戲?yàn)槔?#xff0c;其性能和視覺質(zhì)量至關(guān)重要。在瀏覽器中開發(fā)游戲的需求是有的,但大多數(shù)游戲使用的是 GPU 提供的 3D 圖形 API。Mozilla 和 Opera 公布了一些從 “canvas” 元素中暴露出 3D 渲染上下文的實(shí)驗(yàn),其結(jié)果非常具有吸引力,因此社區(qū)決定一起將大家都可以實(shí)現(xiàn)的內(nèi)容進(jìn)行標(biāo)準(zhǔn)化。

所有的瀏覽器引擎協(xié)作創(chuàng)建了 WebGL,這是在 Web 上渲染 3D 圖形的標(biāo)準(zhǔn)。它基于 OpenGL ES —— 一種面向嵌入式系統(tǒng)的跨平臺(tái)圖形 API。這個(gè)起點(diǎn)是正確的,因?yàn)樗梢暂p松地在所有瀏覽器中實(shí)現(xiàn)相同的 API,而且大多數(shù)瀏覽器引擎都在支持 OpenGL 的系統(tǒng)上運(yùn)行。即使系統(tǒng)沒有直接支持 OpenGL,像 ANGLE 這樣的項(xiàng)目也可以在其他技術(shù)之上進(jìn)行仿真,畢竟這種 API 的抽象級(jí)別是很高的。隨著 OpenGL 的發(fā)展,WebGL 也可以跟著發(fā)展。

WebGL 已經(jīng)在開放平臺(tái)上賦予了開發(fā)人員圖形處理器的功能,所有主流瀏覽器都支持 WebGL 1,使得可以在 Web 上開發(fā)出高質(zhì)量的游戲(console-quality games),也促進(jìn)了 three.js 等第三方庫(kù)的蓬勃發(fā)展。此后,該標(biāo)準(zhǔn)發(fā)展成為 WebGL 2,包括 WebKit 在內(nèi)的所有主流瀏覽器引擎都承諾對(duì)它提供支持。

接下來呢?

在 WebGL 發(fā)展的同時(shí),GPU 技術(shù)也在發(fā)展進(jìn)步,而且已經(jīng)創(chuàng)建了新的軟件 API,能夠更好地反映現(xiàn)代 GPU 的設(shè)計(jì)特性。這些新 API 的抽象級(jí)別比較低,并且由于其降低了開銷,通常來說比 OpenGL 的性能更好。該領(lǐng)域的主要技術(shù)平臺(tái)有微軟的 Direct3D 12、蘋果的 Metal 和 Khronos Group 的 Vulkan。雖然這些技術(shù)的設(shè)計(jì)理念都是相似的,但可惜的是沒有一項(xiàng)技術(shù)是跨平臺(tái)可用的。

那么這對(duì) Web 意味著什么呢?從充分利用 GPU 的角度來講,這些新技術(shù)無疑是未來的發(fā)展方向。Web 平臺(tái)想要成功必須定義一種允許多個(gè)系統(tǒng)上實(shí)現(xiàn)的通用標(biāo)準(zhǔn),而現(xiàn)在已經(jīng)有幾個(gè)在架構(gòu)上稍有差別的圖形 API 了。要開發(fā)一款可以加速圖形和計(jì)算的現(xiàn)代化底層技術(shù),必須設(shè)計(jì)一個(gè)可以在多種系統(tǒng)(包括上面提到的那些系統(tǒng))上實(shí)現(xiàn)的 API。隨著圖形技術(shù)的蓬勃發(fā)展,繼續(xù)遵循像 OpenGL 這樣的某個(gè)特定 API 標(biāo)準(zhǔn)顯然是不可行的。

相反,我們需要評(píng)估和設(shè)計(jì)一個(gè)新的 Web 標(biāo)準(zhǔn):它能夠提供一組核心功能,以及一個(gè)支持多種系統(tǒng)圖形技術(shù)和平臺(tái)的 API,此外還要保障 Web 所要求的保密性和安全性。

再者,我們還需要考慮如何在圖形處理之外使用 GPU,以及新標(biāo)準(zhǔn)如何與其他 Web 技術(shù)協(xié)同工作。該標(biāo)準(zhǔn)應(yīng)該暴露現(xiàn)代 GPU 的通用計(jì)算功能。其設(shè)計(jì)架構(gòu)應(yīng)符合 Web 的既定模式以便開發(fā)和使用。它需要能夠與其他重要的新興 Web 標(biāo)準(zhǔn)(如 WebAssembly 和 WebVR)協(xié)同工作。最重要的是,這個(gè)標(biāo)準(zhǔn)的制定應(yīng)該是一個(gè)開放的過程,允許行業(yè)專家和更廣泛的網(wǎng)絡(luò)社區(qū)參與。

W3C 為這種情況提供了社區(qū)群組平臺(tái)。“Web 端的 GPU” 社區(qū)群組現(xiàn)已開放會(huì)員注冊(cè)。

WebKit 的初始 API 提案

幾年前我們就預(yù)估了下一代圖形 API 的發(fā)展情況,并著手在 WebKit 中設(shè)計(jì)原型以驗(yàn)證我們可以將非常低級(jí)別的 GPU API 暴露給 Web 同時(shí)還可以獲得有價(jià)值的性能提升。我們得到了一些非常鼓舞人心的實(shí)驗(yàn)結(jié)果,所以我們將原型分享給了 W3C 社區(qū)群組。我們也準(zhǔn)備將代碼部署到 WebKit 中,所以你很快就可以自己去嘗試了。我們并不奢望這一 API 本身能成為最后的標(biāo)準(zhǔn),社區(qū)也有可能根本就不會(huì)從它入手,但是我們認(rèn)為編寫代碼的工作本身是很有價(jià)值的。其他瀏覽器引擎也已經(jīng)開發(fā)了類似的原型。與社區(qū)合作并為計(jì)算機(jī)圖形提出一個(gè)偉大的新技術(shù)想必是一件十分令人激動(dòng)的事情。

下文將詳細(xì)闡述我們的實(shí)驗(yàn),我們將它稱為 “WebGPU”。

獲取渲染上下文(Rendering Context)和渲染管道(Rendering Pipeline)

不出意料,WebGPU 的接口是通過 “canvas” 元素來訪問的。

let canvas = document.querySelector("canvas"); let gpu = canvas.getContext("webgpu");復(fù)制代碼

WebGPU 比 WebGL 要更加面向?qū)ο蠡?#xff0c;事實(shí)上這也是性能提升的緣由之一。WebGPU 允許你創(chuàng)建和存儲(chǔ)表示狀態(tài)的對(duì)象和可以處理一組命令的對(duì)象,而無需在每次繪制操作之前設(shè)置狀態(tài)。這樣,我們可以在狀態(tài)創(chuàng)建時(shí)就執(zhí)行一些驗(yàn)證工作,從而減少繪圖時(shí)的工作量。

WebGPU 上下文暴露了圖形命令和并行計(jì)算命令。假設(shè)需要繪制一些圖形,這需要用到圖形管道。圖形管道中最重要的元素是著色器(shaders),它們是在 GPU 上運(yùn)行用以處理幾何數(shù)據(jù)并為每個(gè)像素的繪制提供顏色的程序。著色器通常用專門用于圖形的編程語言進(jìn)行編寫。

決定 Web API 使用何種著色語言是件有趣的事情,因?yàn)橛泻芏嘁蛩匦枰紤]。我們需要一種功能強(qiáng)大的語言,要求編程盡量簡(jiǎn)單、能序列化為可高效傳輸?shù)母袷?#xff0c;并要求可以由瀏覽器進(jìn)行驗(yàn)證以確保著色器的安全性。業(yè)內(nèi)有部分人傾向于使用可以從許多源格式生成的著色器表示,這有點(diǎn)類似于匯編語言。同時(shí),在“查看源代碼”方面 Web 可謂發(fā)展迅速,對(duì)人而言代碼的可讀性還是很重要的。我們期望關(guān)于著色語言的討論成為標(biāo)準(zhǔn)化過程中最有趣的部分之一,我們也十分愿意聽取社區(qū)的意見。

就 WebGPU 原型而言,我們決定暫不考慮著色語言的問題,而是直接采用一種現(xiàn)存的語言。因?yàn)槲覀儺?dāng)時(shí)的工作是建立在蘋果的平臺(tái)上的,所以我們選擇了Metal Shading Language。那接下來的問題就是如何將著色器加載到 WebGPU 了。

let library = gpu.createLibrary( /* 源代碼 */ );let vertexFunction = library.functionWithName("vertex_main"); let fragmentFunction = library.functionWithName("fragment_main");復(fù)制代碼

我們使用 gpu 對(duì)象從源代碼加載并編譯著色器,生成一個(gè) WebGPULibrary。著色器代碼本身并不重要 —— 其實(shí)就是一個(gè)非常簡(jiǎn)單的頂點(diǎn)(vertex)和片段(fragment)的組合。一個(gè) WebGPULibrary 可以容納多個(gè)著色器函數(shù),因此我們通過函數(shù)名稱取出將要在管道中用到的相應(yīng)函數(shù)。

現(xiàn)在我們就可以創(chuàng)建管道了。

// 管道的一些細(xì)節(jié)。 let pipelineDescriptor = new WebGPURenderPipelineDescriptor(); pipelineDescriptor.vertexFunction = vertexFunction; pipelineDescriptor.fragmentFunction = fragmentFunction; pipelineDescriptor.colorAttachments[0].pixelFormat = "BGRA8Unorm";let pipelineState = gpu.createRenderPipelineState(pipelineDescriptor);復(fù)制代碼

傳入所需描述信息(包括使用的頂點(diǎn)、片段著色器以及圖像格式)即可從上下文中得到一個(gè)新的 WebGPURenderPipelineState 對(duì)象。

緩沖區(qū)(Buffers)

繪圖操作要求使用緩沖區(qū)向渲染管道提供數(shù)據(jù),例如幾何坐標(biāo)、顏色、法向量等等,而 WebGPUBuffer 則是容納這些數(shù)據(jù)的對(duì)象。

let vertexData = new Float32Array([ /* some data */ ]); let vertexBuffer = gpu.createBuffer(vertexData);復(fù)制代碼

此例中,我們有一個(gè) Float32Array,它包含了需要在幾何圖形中繪制的每個(gè)頂點(diǎn)的數(shù)據(jù)。我們從 Float32Array 創(chuàng)建一個(gè) WebGPUBuffer,該緩沖區(qū)會(huì)在之后的繪圖操作中用到。

諸如此類的頂點(diǎn)數(shù)據(jù)很少發(fā)生變化,但也有些數(shù)據(jù)是幾乎每次繪制時(shí)都會(huì)發(fā)生變化的。像這種不變的數(shù)據(jù)被稱為 uniforms。表示相機(jī)位置的當(dāng)前變換矩陣即是 uniform 的一個(gè)很常見的例子。WebGPUBuffer 也可用于 uniform,但此處我們希望在創(chuàng)建之后將其寫入緩沖區(qū)。

// 將 "buffer" 看作是一個(gè)之前分配好的 WebGPUBuffer。 // buffer.contents 暴露一個(gè) ArrayBufferView,我們將其 // 解析為一個(gè) 32 位的浮點(diǎn)數(shù)數(shù)組。 let uniforms = new Float32Array(buffer.contents);// 設(shè)置所需 uniform。 uniforms[42] = Math.PI;復(fù)制代碼

這樣做的好處之一是 JavaScript 開發(fā)人員可以將 ArrayBufferView 封裝在帶有自定義 getter 和 setter 的類或代理對(duì)象(Proxy object)中,這樣外部接口看起來像典型的 JavasScript 對(duì)象一樣。然后,包裝器對(duì)象會(huì)更新緩沖區(qū)正在使用的底層數(shù)組中的相應(yīng)部分。

繪圖(Drawing)

在通知 WebGPU 上下文繪圖之前還需要設(shè)置一些狀態(tài),這包括渲染的目標(biāo)位置(最終將在 canvas 中顯示的 WebGPUTexture)以及紋理(texture)初始化和使用情況的描述信息。這些狀態(tài)存儲(chǔ)在 WebGPURenderPassDescriptor 中。

// 從上下文獲取下一幀所期望的紋理信息。 let drawable = gpu.nextDrawable();let passDescriptor = new WebGPURenderPassDescriptor(); passDescriptor.colorAttachments[0].loadAction = "clear"; passDescriptor.colorAttachments[0].storeAction = "store"; passDescriptor.colorAttachments[0].clearColor = [0.8, 0.8, 0.8, 1.0]; passDescriptor.colorAttachments[0].texture = drawable.texture;復(fù)制代碼

首先,我們向 WebGPU 上下文請(qǐng)求一個(gè)表示下一可繪幀的對(duì)象,此對(duì)象最終會(huì)被復(fù)制到 canvas 元素中去。完成繪圖代碼后,我們要通知 WebGPU 以便其顯示繪圖結(jié)果并準(zhǔn)備下一個(gè)可繪幀。

從初始化 WebGPURenderPassDescriptor 的代碼中可以看出,我們不會(huì)在繪圖操作正在進(jìn)行的時(shí)候從紋理中讀取信息(因?yàn)?loadAction 的值是 clear),而是在繪圖操作完成之后才使用該紋理(因?yàn)?storeAction 的值是 store),此外代碼還指定了紋理的填充顏色。

接下來,我們創(chuàng)建用于保存實(shí)際繪制操作的對(duì)象。一個(gè) WebGPUCommandQueue 有一組 WebGPUCommandBuffers。我們使用 WebGPUCommandEncoder 將操作推送到 WebGPUCommandBuffer 中去。

let commandQueue = gpu.createCommandQueue(); let commandBuffer = commandQueue.createCommandBuffer();// 使用之前創(chuàng)建的描述符。 let commandEncoder = commandBuffer.createRenderCommandEncoderWithDescriptor(passDescriptor);// 告知編碼器使用何種狀態(tài)(例如:著色器)。 commandEncoder.setRenderPipelineState(pipelineState);// 最后,編碼器還需要知道使用哪個(gè)緩沖區(qū)。 commandEncoder.setVertexBuffer(vertexBuffer, 0, 0);復(fù)制代碼

至此,我們已經(jīng)設(shè)置好了一個(gè)渲染管道,其中包含若干著色器、一個(gè)用于保存幾何信息的緩沖區(qū)、一個(gè)用于保存繪制操作的隊(duì)列以及一個(gè)可以提交到該隊(duì)列的編碼器。現(xiàn)在只需將實(shí)際繪圖命令推入編碼器即可。

// 我們知道我們的緩沖區(qū)有 3 個(gè)頂點(diǎn), // 我們希望繪制出一個(gè)填充的三角形。 commandEncoder.drawPrimitives("triangle", 0, 3); commandEncoder.endEncoding();// 所有繪圖命令已經(jīng)提交。通知 WebGPU // 一旦隊(duì)列處理完畢即刻顯示 canvas 中的繪圖結(jié)果。 commandBuffer.presentDrawable(drawable); commandBuffer.commit();復(fù)制代碼

像大多數(shù) 3D 圖形的示例代碼一樣,繪制一個(gè)簡(jiǎn)單的形狀看起來要寫很多代碼,但其實(shí)并非如此。這些現(xiàn)代 API 有一個(gè)優(yōu)點(diǎn) —— 其大部分代碼都是在創(chuàng)建可以重用以繪制其他內(nèi)容的對(duì)象。例如,一般渲染上下文只需要一個(gè) WebGPUCommandQueue 實(shí)例,又者可以為不同的著色器提前創(chuàng)建多個(gè) WebGPURenderPipelineState 對(duì)象。此外,瀏覽器還可以在前期進(jìn)行很多驗(yàn)證工作,從而減少繪圖操作過程中的開銷。

希望本文可以讓你對(duì) WebGPU 提案有一個(gè)大致了解。盡管由 W3C 社區(qū)群組最終確定的 API 可能同此提案有很大不同,但我們相信很多一般的設(shè)計(jì)原則都是通用的。

公開邀請(qǐng)

蘋果的 WebKit 團(tuán)隊(duì)已經(jīng)建議為 Web 端 GPU 建立一個(gè) W3C 社區(qū)群組作為工作論壇,同時(shí)也請(qǐng)你加入我們一起定義 GPU 的下一代標(biāo)準(zhǔn)。我們的建議得到了其他瀏覽器引擎開發(fā)商、GPU 供應(yīng)商、框架開發(fā)人員等業(yè)內(nèi)同仁的積極回應(yīng)。在行業(yè)的支持下,我們誠(chéng)邀所有對(duì) Web GPU 感興趣或有專長(zhǎng)的人加入社區(qū)群組。


掘金翻譯計(jì)劃 是一個(gè)翻譯優(yōu)質(zhì)互聯(lián)網(wǎng)技術(shù)文章的社區(qū),文章來源為 掘金 上的英文分享文章。內(nèi)容覆蓋 Android、iOS、React、前端、后端、產(chǎn)品、設(shè)計(jì) 等領(lǐng)域,想要查看更多優(yōu)質(zhì)譯文請(qǐng)持續(xù)關(guān)注 掘金翻譯計(jì)劃。

總結(jié)

以上是生活随笔為你收集整理的Web 端的下一代三维图形的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。