<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>http://www.webgl3d.cn/</title>
</head>
<body>
<canvas id="webgpu" width="500" height="500"></canvas>
<script type="module">
if (navigator.gpu) {
console.log('你的浏览器支持WebGPU。');
} else {
console.log('你的浏览器不支持WebGPU,请更换新版本浏览器。');
}
const adapter = await navigator.gpu.requestAdapter()
const device = await adapter.requestDevice()
const canvas = document.getElementById("webgpu")
const context = canvas.getContext("webgpu")
const format = navigator.gpu.getPreferredCanvasFormat();//获取浏览器默认的颜色格式
context.configure({
device: device,
format: format,//颜色格式
});
const vertexArray = new Float32Array([
// 三角形三个顶点坐标的x、y、z值
0.0, 0.0, 0.0,//顶点1坐标
1.0, 0.0, 0.0,//顶点2坐标
0.0, 1.0, 0.0,//顶点3坐标
]);
const vertexBuffer = device.createBuffer({
size: vertexArray.byteLength,//顶点数据的字节长度
//usage设置该缓冲区的用途(作为顶点缓冲区|可以写入顶点数据)
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
//把vertexArray里面的顶点数据写入到vertexBuffer对应的GPU显存缓冲区中
//参数2的0表示从vertexArray的数据开头读取数据。
device.queue.writeBuffer(vertexBuffer, 0, vertexArray);
// 引入顶点着色器vertex代码对应字符串
import { vertex, fragment } from './shader.js'
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
// 顶点着色器
module: device.createShaderModule({ code: vertex }),
entryPoint: "main",
buffers: [// 顶点所有的缓冲区模块设置
{//其中一个顶点缓冲区设置
arrayStride: 3 * 4,//一个顶点数据占用的字节长度,
//该缓冲区一个顶点包含xyz三个分量,
//每个数字是4字节浮点数,3*4字节长度
attributes: [{// 顶点缓冲区属性
shaderLocation: 0,//GPU显存上顶点缓冲区标记存储位置
format: "float32x2",//格式:loat32x3表示一个顶点数据包含3个32位浮点数
offset: 0//arrayStride表示每组顶点数据间隔字节数,offset表示读取改组的偏差字节数,没特殊需要一般设置0
},{// 顶点缓冲区属性
shaderLocation: 1,//GPU显存上顶点缓冲区标记存储位置
format: "float32",//格式:loat32x3表示一个顶点数据包含3个32位浮点数
offset: 2*4//arrayStride表示每组顶点数据间隔字节数,offset表示读取改组的偏差字节数,没特殊需要一般设置0
}]
}
]
},
fragment: {
module: device.createShaderModule({ code: fragment }),
entryPoint: "main",
targets: [{
format: format//和WebGPU上下文配置的颜色格式保持一致
}]
},
primitive: {
topology: "triangle-list",//三角形绘制顶点数据
}
});
// 创建GPU命令编码器对象
const commandEncoder = device.createCommandEncoder();
const renderPass = commandEncoder.beginRenderPass({
// 给渲染通道指定颜色缓冲区,配置指定的缓冲区
colorAttachments: [{
// 指向用于Canvas画布的纹理视图对象(Canvas对应的颜色缓冲区)
// 该渲染通道renderPass输出的像素数据会存储到Canvas画布对应的颜色缓冲区(纹理视图对象)
view: context.getCurrentTexture().createView(),
storeOp: 'store',//像素数据写入颜色缓冲区
loadOp: 'clear',
clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 }, //背景颜色
}]
});
// 设置该渲染通道控制渲染管线
renderPass.setPipeline(pipeline);
//顶点缓冲区数据和渲染管线shaderLocation: 0表示存储位置关联起来
renderPass.setVertexBuffer(0, vertexBuffer);
// 绘制命令.draw()绘制顶点数据
renderPass.draw(3);
// 渲染通道结束命令.end()
renderPass.end();
// 命令编码器.finish()创建命令缓冲区(生成GPU指令存入缓冲区)
const commandBuffer = commandEncoder.finish();
// 命令编码器缓冲区中命令传入GPU设备对象的命令队列.queue
device.queue.submit([commandBuffer]);
</script>
</body>
</html>