webgpu用最简短的代码画一个三角形
1.包含webgpu的初始化
2.三角形顶点缓冲的创建以及将cpu数据填充到gpu里
3.webgpu里着色器的编写,以及通过代码创建webgpu的着色器程序对象
4.通过顶点和像素阶段的描述创建一个渲染管线
话不多说直接贴代码:
<html>
<head>
<meta charset="utf-8">
<title>WebGPU Hello Triangle</title>
<style>
body {
font-family: system-ui;
color: #f7f7ff;
background-color: rgb(38, 38, 38);
text-align: center;
}
canvas {
display: block;
margin: 0 auto;
width: 100%;
height: 100%;
}
</style>
<script type="module">
// 获取canvas元素
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 获取WebGPU上下文
const context = canvas.getContext("webgpu");
// 定义顶点数据,三个顶点组成一个三角形
const vertices = new Float32Array([
-0.5, -0.5, 1.0, 0.0, 0.0, 1.0, // 左下角
0.5, -0.5, 0.0, 1.0, 0.0, 1.0, // 右下角
0.0, 0.5, 0.0, 0.0, 1.0, 1.0, // 顶点
]);
// 定义顶点着色器代码,使用WGSL语言
const wgslSource = `
struct Vertex {
@builtin(position) Position: vec4<f32>, // 顶点着色器输出的位置
@location(0) color: vec4<f32>, // 顶点着色器输出的颜色
}
// 顶点着色器
@vertex fn vsmain(
@builtin(vertex_index) VertexIndex: u32, // 顶点着色器内建的顶点索引
@location(0) position: vec2<f32>, // 输入顶点的位置
@location(1) color: vec4<f32> // 输入顶点的颜色
) -> Vertex
{
var vertex_out : Vertex;
vertex_out.Position = vec4<f32>(position, 0.0, 1.0);
vertex_out.color = color;
return vertex_out;
}
// 像素着色器
@fragment fn fsmain(in: Vertex) -> @location(0) vec4<f32>
{
return in.color;
}
`;
// 初始化WebGPU相关对象
async function initWebGPU() {
// 获取适配器对象,表示GPU的物理设备
const adapter = await navigator.gpu.requestAdapter();
// 获取设备对象,表示GPU的会话
const device = await adapter.requestDevice();
// 配置上下文对象,指定设备和像素格式
const format = "bgra8unorm";
context.configure({
device: device,
format: format,
});
// 创建顶点缓冲区,用于存储顶点数据
const vertexBuffer = device.createBuffer({
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: true,
});
new Float32Array(vertexBuffer.getMappedRange()).set(vertices);
vertexBuffer.unmap();
// 创建着色器模块,用于编译着色器代码
const shaderModule = device.createShaderModule({ code: wgslSource });
// 定义顶点输入的数据布局,以及顶点着色阶段的其它信息
const vertexSize = 4 * 6;
const colorOffset = 4 * 2;
const positionAttributeState = {
format: "float32x2",
offset: 0,
shaderLocation: 0,
};
const colorAttributeState = {
format: "float32x4",
offset: colorOffset,
shaderLocation: 1,
}
const vertexBufferState = {
arrayStride: vertexSize,
stepMode: "vertex",
attributes: [positionAttributeState, colorAttributeState], // 顶点输入属性包含一个位置和颜色
};
const vertexStageDescriptor = {
buffers: [vertexBufferState], // 顶点着色的顶点缓冲
module: shaderModule, // 顶点着色的shader
entryPoint: "vsmain" // 入口函数
};
const fragmentStageDescriptor = {
module: shaderModule,
entryPoint: "fsmain",
targets: [ {format: "bgra8unorm" }, ],
};
const renderPipelineDescriptor = {
layout: 'auto',
vertex: vertexStageDescriptor,
fragment: fragmentStageDescriptor,
primitive: {topology: "triangle-list" },
};
// 创建渲染管线,用于指定渲染流程和状态
const pipeline = device.createRenderPipeline(renderPipelineDescriptor);
return { device, pipeline, vertexBuffer }; // 返回相关对象
}
// 渲染函数,用于绘制图形
function render({ device, pipeline, vertexBuffer }) {
// 获取颜色纹理,用于存储渲染结果
const textureView = context.getCurrentTexture().createView();
// 创建命令编码器,用于记录渲染命令
const commandEncoder = device.createCommandEncoder();
const colorAttachmentDescriptor = {
view: textureView,
loadOp: "clear",
storeOp: "store",
clearColor: [0.5, 0.5, 0.5, 1]
};
/* GPURenderPassDescriptor */
const renderPassDescriptor = { colorAttachments: [colorAttachmentDescriptor] };
// 开始一个渲染通道,指定颜色附件和清除颜色
const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor);
// 设置渲染管线
renderPass.setPipeline(pipeline);
// 设置顶点缓冲区
renderPass.setVertexBuffer(0, vertexBuffer);
// 绘制三个顶点,组成一个三角形
renderPass.draw(3, 1, 0, 0);
// 结束渲染通道
renderPass.end();
// 结束命令编码器,获取命令缓冲区
const commandBuffer = commandEncoder.finish();
// 将命令缓冲区提交给GPU队列,执行渲染命令
device.queue.submit([commandBuffer]);
}
// 调用初始化函数,然后调用渲染函数
initWebGPU().then(render);
</script>
</head>
<body>
<canvas id="canvas" ></canvas>
</body>
</html>
效果如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)