• Google codelab WebGPU入门教程源码<4> - 使用Uniform类型对象给着色器传数据(源码)


    对应的教程文章: 

    https://codelabs.developers.google.com/your-first-webgpu-app?hl=zh-cn#5

    对应的源码执行效果:

    对应的教程源码: 

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

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

  • 相关阅读:
    React经典初级错误
    【车间调度】基于模拟退火优化算法的的并行车间机器优化调度(Matlab代码实现)
    【c++刷题Day3】专题5数组标记&哈希T3
    【云原生】Apache Livy on k8s 讲解与实战操作
    深度学习(PyTorch)——DataLoader的使用方法
    网易Airtest全新推出:小型便携式集群解决方案!
    【LinuxC】时间、时区,相关命令、函数
    Vue-组件通信6种方式
    MySQL的DDL语句
    Google Earth Engine(GEE)教程——数字矢量集合aggregate_array函数进行矢量转化为数组和区分不同分析
  • 原文地址:https://blog.csdn.net/vily_lei/article/details/134438879