WebGPU 01之Hello Triangle
1. 引言
WebGPU是什么?
WebGPU与WebGL的对比?
2. 快速体验
参考:Orillusion | 专业WebGPU社区 | WebGPU小白入门(一): 零基础创建第一个WebGPU项目
# Clone the repo
git clone https://github.com/Orillusion/orillusion-webgpu-samples.git
# Go inside the folder
cd orillusion-webgpu-samples
# Start installing dependencies
npm install #or yarn add
# Run project at localhost:3000
npm run dev #or yarn run dev
在Chrome 浏览器(版本100+) 中打开localhost:3000
,即可看到运行结果:
注意:
目前(2022年7月)WebGPU未正式发布,接口代码变更较快
WebGPU未正式发布,各个浏览器支持程度不同,本文使用Chrome版本号为:105.0.5153.0(正式版本)canary (64 位),下载地址:开发者专用的 Chrome Canary 版功能 - Google Chrome
部署别人写的代码终究是少了点感觉,接下来将编写一个入手案例
3. Hello Triangle
3.1 环境准备
浏览器:Chrome Canary版,版本号为:105.0.5153.0(正式版本)canary (64 位)
将Chrome开启WebGPU功能:
在地址栏输入 chrome://flags/
搜索 WebGPU
,将WebGPU的功能打开
3.2 基础代码
创建一个HTML文件,设置基础代码,另外,WebGPU是借助HTML中的canvas
元素实现的,所以创建一个canvas
元素
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Basic Triangle</title>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
background: #000;
color: #fff;
display: flex;
text-align: center;
flex-direction: column;
justify-content: center;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas></canvas>
<script src="./index.js"></script>
</body>
</html>
3.3 主要代码
同一目录下创建一个index.js
文件,代码内容如下,流程讲解在下一节
index.js:
// initialize webgpu device & config canvas context
async function initWebGPU(canvas) {
if(!navigator.gpu)
throw new Error('Not Support WebGPU')
const adapter = await navigator.gpu.requestAdapter({
powerPreference: 'high-performance'
// powerPreference: 'low-power'
})
if (!adapter)
throw new Error('No Adapter Found')
const device = await adapter.requestDevice()
const context = canvas.getContext('webgpu')
const format = navigator.gpu.getPreferredCanvasFormat ? navigator.gpu.getPreferredCanvasFormat() : context.getPreferredFormat(adapter)
const devicePixelRatio = window.devicePixelRatio || 1
canvas.width = canvas.clientWidth * devicePixelRatio
canvas.height = canvas.clientHeight * devicePixelRatio
const size = {width: canvas.width, height: canvas.height}
context.configure({
// json specific format when key and value are the same
device, format,
// prevent chrome warning
alphaMode: 'opaque'
})
return {device, context, format, size}
}
// create a simple pipiline
async function initPipeline(device, format){
const descriptor = {
layout: 'auto',
vertex: {
module: device.createShaderModule({
code: `@vertex
fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4<f32> {
var pos = array<vec2<f32>, 3>(
vec2<f32>(0.0, 0.5),
vec2<f32>(-0.5, -0.5),
vec2<f32>(0.5, -0.5)
);
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
}`
}),
entryPoint: 'main'
},
primitive: {
topology: 'triangle-list' // try point-list, line-list, line-strip, triangle-strip?
},
fragment: {
module: device.createShaderModule({
code: `@fragment
fn main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}`
}),
entryPoint: 'main',
targets: [
{
format: format
}
]
}
}
return await device.createRenderPipelineAsync(descriptor)
}
// create & submit device commands
function draw(device, context, pipeline) {
const commandEncoder = device.createCommandEncoder()
const view = context.getCurrentTexture().createView()
const renderPassDescriptor = {
colorAttachments: [
{
view: view,
clearValue: { r: 0, g: 0, b: 0, a: 1.0 },
loadOp: 'clear', // clear/load
storeOp: 'store' // store/discard
}
]
}
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor)
passEncoder.setPipeline(pipeline)
// 3 vertex form a triangle
passEncoder.draw(3)
passEncoder.end()
// webgpu run in a separate process, all the commands will be executed after submit
device.queue.submit([commandEncoder.finish()])
}
async function run(){
const canvas = document.querySelector('canvas')
if (!canvas)
throw new Error('No Canvas')
const {device, context, format} = await initWebGPU(canvas)
const pipeline = await initPipeline(device, format)
// start draw
draw(device, context, pipeline)
// re-configure context on resize
window.addEventListener('resize', ()=>{
canvas.width = canvas.clientWidth * devicePixelRatio
canvas.height = canvas.clientHeight * devicePixelRatio
// don't need to recall context.configure() after v104
draw(device, context, pipeline)
})
}
run()
运行代码(笔者这里使用VS Code和Live Server插件),使用Chrome打开,顺利的话即可看到三角形:
4. 运行流程
5. 参考资料
[1]WebGPU 到底是什么? - 知乎 (zhihu.com)
[2]WebGPU学习系列目录 - Wonder-YYC - 博客园 (cnblogs.com)
[3]WebGPU性能测试分析 - Wonder-YYC - 博客园 (cnblogs.com)
[4]WebGL 与 WebGPU 比对 前奏 - 四季留歌 - 博客园 (cnblogs.com)
[7]Orillusion | 专业WebGPU社区 | WebGPU小白入门(一): 零基础创建第一个WebGPU项目
[8]WebGPU小白入门(二):绘制简单三角形——1.认识渲染流程_哔哩哔哩_bilibili
最新文章
- 《Play for Java》学习笔记(二)基本的CRUD应用
- (转)WebApi自动生成在线文档Swashbuckle
- 从零开始,让你的框架支持CocoaPods
- 第一篇、Swift_Textkit的基本使用
- 如何设置虚拟机、开发板、windows IP才能互相PING通
- Tomcat—怎样在Tomcat Webserver下部署Web项目
- php正则表达式手册
- [编织消息框架][netty源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现
- 替换Spring Boot 的EnableCaching注解
- Javascript、CSS、HTML面试题
- Golang 入门系列(二)学习Go语言需要注意的坑
- namenode No valid image files
- erlang下lists模块sort(排序)方法源码解析(二)
- top和nvidia-smi无法显示占用GPU的PID问题
- linux上安装mysql5.6
- Codeforces965E Short Code 【启发式合并】【堆】
- Linux系统安全笔记
- 轻量级web富文本框——wangEditor使用手册(1)——基本应用 demo
- GC那些事儿--Android内存优化第一弹
- [vue]v-bind: sytle/class-bind&;属性值绑定