• Google codelab WebGPU入门教程源码<3> - 绘制网格(源码)


    对应的教程文章: https://codelabs.developers.google.com/your-first-webgpu-app?hl=zh-cn#4

    对应的源码执行效果: 

    对应的教程源码: 

    此处源码和教程本身提供的部分代码可能存在一点差异。

    1. class Color4 {
    2. r: number;
    3. g: number;
    4. b: number;
    5. a: number;
    6. constructor(pr = 1.0, pg = 1.0, pb = 1.0, pa = 1.0) {
    7. this.r = pr;
    8. this.g = pg;
    9. this.b = pb;
    10. this.a = pa;
    11. }
    12. }
    13. export class WGPURColorGrid {
    14. private mRVertices: Float32Array = null;
    15. private mRPipeline: any | null = null;
    16. private mVtxBuffer: any | null = null;
    17. private mCanvasFormat: any | null = null;
    18. private mWGPUDevice: any | null = null;
    19. private mWGPUContext: any | null = null;
    20. private mUniformBindGroup: any | null = null;
    21. private mGridSize = 32;
    22. constructor() {}
    23. initialize(): void {
    24. const canvas = document.createElement("canvas");
    25. canvas.width = 512;
    26. canvas.height = 512;
    27. document.body.appendChild(canvas);
    28. this.initWebGPU(canvas).then(() => {
    29. console.log("webgpu initialization finish ...");
    30. this.clearWGPUCanvas();
    31. });
    32. document.onmousedown = (evt):void => {
    33. this.clearWGPUCanvas( new Color4( Math.random(), Math.random(), Math.random()) );
    34. }
    35. }
    36. private createUniform(device: any, pipeline: any): void {
    37. // Create a uniform buffer that describes the grid.
    38. const uniformArray = new Float32Array([this.mGridSize, this.mGridSize]);
    39. const uniformBuffer = device.createBuffer({
    40. label: "Grid Uniforms",
    41. size: uniformArray.byteLength,
    42. usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
    43. });
    44. device.queue.writeBuffer(uniformBuffer, 0, uniformArray);
    45. this.mUniformBindGroup = device.createBindGroup({
    46. label: "Cell renderer bind group",
    47. layout: pipeline.getBindGroupLayout(0),
    48. entries: [{
    49. binding: 0,
    50. resource: { buffer: uniformBuffer }
    51. }],
    52. });
    53. }
    54. private createRectGeometryData(device: any, pass: any): void {
    55. let vertices = this.mRVertices;
    56. let vertexBuffer = this.mVtxBuffer;
    57. let cellPipeline = this.mRPipeline;
    58. if(!cellPipeline) {
    59. let hsize = 0.8;
    60. vertices = new Float32Array([
    61. // X, Y,
    62. -hsize, -hsize, // Triangle 1 (Blue)
    63. hsize, -hsize,
    64. hsize, hsize,
    65. -hsize, -hsize, // Triangle 2 (Red)
    66. hsize, hsize,
    67. -hsize, hsize,
    68. ]);
    69. vertexBuffer = device.createBuffer({
    70. label: "Cell vertices",
    71. size: vertices.byteLength,
    72. usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
    73. });
    74. device.queue.writeBuffer(vertexBuffer, /*bufferOffset=*/0, vertices);
    75. const vertexBufferLayout = {
    76. arrayStride: 8,
    77. attributes: [{
    78. format: "float32x2",
    79. offset: 0,
    80. shaderLocation: 0, // Position, see vertex shader
    81. }],
    82. };
    83. const shaderCodes = `
    84. struct VertexInput {
    85. @location(0) pos: vec2f,
    86. @builtin(instance_index) instance: u32,
    87. };
    88. struct VertexOutput {
    89. @builtin(position) pos: vec4f,
    90. @location(0) cell: vec2f,
    91. };
    92. @group(0) @binding(0) var grid: vec2f;
    93. @vertex
    94. fn vertexMain(input: VertexInput) -> VertexOutput {
    95. let i = f32(input.instance);
    96. let cell = vec2f(i % grid.x, floor(i / grid.x));
    97. let cellOffset = cell / grid * 2;
    98. let gridPos = (input.pos + 1) / grid - 1 + cellOffset;
    99. var output: VertexOutput;
    100. output.pos = vec4f(gridPos, 0, 1);
    101. output.cell = cell;
    102. return output;
    103. }
    104. @fragment
    105. fn fragmentMain(input: VertexOutput) -> @location(0) vec4f {
    106. let c = input.cell/grid;
    107. return vec4f(c, 1.0 - c.x, 1);
    108. }
    109. `;
    110. const cellShaderModule = device.createShaderModule({
    111. label: "Cell shader",
    112. code: shaderCodes
    113. });
    114. cellPipeline = device.createRenderPipeline({
    115. label: "Cell pipeline",
    116. layout: "auto",
    117. vertex: {
    118. module: cellShaderModule,
    119. entryPoint: "vertexMain",
    120. buffers: [vertexBufferLayout]
    121. },
    122. fragment: {
    123. module: cellShaderModule,
    124. entryPoint: "fragmentMain",
    125. targets: [{
    126. format: this.mCanvasFormat
    127. }]
    128. },
    129. });
    130. this.mRVertices = vertices;
    131. this.mVtxBuffer = vertexBuffer;
    132. this.mRPipeline = cellPipeline;
    133. this.createUniform(device, cellPipeline);
    134. }
    135. pass.setPipeline(cellPipeline);
    136. pass.setVertexBuffer(0, vertexBuffer);
    137. pass.setBindGroup(0, this.mUniformBindGroup);
    138. pass.draw(vertices.length / 2, this.mGridSize * this.mGridSize);
    139. }
    140. private clearWGPUCanvas(clearColor: Color4 = null): void {
    141. clearColor = clearColor ? clearColor : new Color4(0.05, 0.05, 0.1);
    142. const device = this.mWGPUDevice;
    143. const context = this.mWGPUContext;
    144. const rpassParam = {
    145. colorAttachments: [
    146. {
    147. clearValue: clearColor,
    148. // clearValue: [0.3,0.7,0.5,1.0], // yes
    149. view: context.getCurrentTexture().createView(),
    150. loadOp: "clear",
    151. storeOp: "store"
    152. }
    153. ]
    154. };
    155. const encoder = device.createCommandEncoder();
    156. const pass = encoder.beginRenderPass( rpassParam );
    157. this.createRectGeometryData(device, pass);
    158. pass.end();
    159. const commandBuffer = encoder.finish();
    160. device.queue.submit([commandBuffer]);
    161. }
    162. private async initWebGPU(canvas: HTMLCanvasElement) {
    163. const gpu = (navigator as any).gpu;
    164. if (gpu) {
    165. console.log("WebGPU supported on this browser.");
    166. const adapter = await gpu.requestAdapter();
    167. if (adapter) {
    168. console.log("Appropriate GPUAdapter found.");
    169. const device = await adapter.requestDevice();
    170. if (device) {
    171. this.mWGPUDevice = device;
    172. console.log("Appropriate GPUDevice found.");
    173. const context = canvas.getContext("webgpu") as any;
    174. const canvasFormat = gpu.getPreferredCanvasFormat();
    175. this.mWGPUContext = context;
    176. this.mCanvasFormat = canvasFormat;
    177. console.log("canvasFormat: ", canvasFormat);
    178. context.configure({
    179. device: device,
    180. format: canvasFormat,
    181. alphaMode: "premultiplied"
    182. });
    183. } else {
    184. throw new Error("No appropriate GPUDevice found.");
    185. }
    186. } else {
    187. throw new Error("No appropriate GPUAdapter found.");
    188. }
    189. } else {
    190. throw new Error("WebGPU not supported on this browser.");
    191. }
    192. }
    193. run(): void {}
    194. }

  • 相关阅读:
    Everything扫描非C盘
    毕业论文中的问卷如何做效度分析?
    LeetCode 热题 HOT 100 第五十七天 221. 最大正方形 中等题 用python3求解
    JAVA学习实战 reactor线程模型
    Vue-06-vue-cli
    积分商城搭建的要点与优势有哪些?
    谷粒商城实战(044集群学习-redis集群)
    【slam十四讲第二版】【课后习题】【第九讲~后端1】
    解析java中的String类中的方法(一)
    聊聊分布式架构08——SpringBoot开启微服务时代
  • 原文地址:https://blog.csdn.net/vily_lei/article/details/134438783