saker200

Script

May 11th, 2022 (edited)
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (async () => {
  2.   var canvas = document.getElementById("renderCanvas");
  3.   var engine = new BABYLON.WebGPUEngine(canvas);
  4.    
  5.   var createScene = function () {
  6.     var scene = new BABYLON.Scene(engine);
  7.  
  8.     var camera = new BABYLON.FreeCamera(
  9.       "camera1",
  10.       new BABYLON.Vector3(0, 5, -10),
  11.       scene
  12.     );
  13.  
  14.     camera.setTarget(BABYLON.Vector3.Zero());
  15.  
  16.     camera.attachControl(canvas, true);
  17.  
  18.     // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
  19.     var light = new BABYLON.HemisphericLight(
  20.       "light",
  21.       new BABYLON.Vector3(0, 1, 0),
  22.       scene
  23.     );
  24.  
  25.     // Default intensity is 1. Let's dim the light a small amount
  26.     light.intensity = 0.7;
  27.  
  28.     // Our built-in 'sphere' shape.
  29.     var sphere = BABYLON.MeshBuilder.CreateSphere(
  30.       "sphere",
  31.       { diameter: 2, segments: 32 },
  32.       scene
  33.     );
  34.  
  35.     // Move the sphere upward 1/2 its height
  36.     sphere.position.y = 1;
  37.  
  38.     // Our built-in 'ground' shape.
  39.     var ground = BABYLON.MeshBuilder.CreateGround(
  40.       "ground",
  41.       { width: 6, height: 6 },
  42.       scene
  43.     );
  44.  
  45.     if (!checkComputeShadersSupported(engine, scene)) {
  46.       return scene;
  47.     }
  48.  
  49.     // -------- COMPUTE 1 -------------------------
  50.     //
  51.     const cs1 = new BABYLON.ComputeShader(
  52.       "myCompute",
  53.       engine,
  54.       { computeSource: copyTextureComputeShader },
  55.       {
  56.         bindingsMapping: {
  57.           dest: { group: 0, binding: 0 },
  58.           src: { group: 0, binding: 2 },
  59.         },
  60.       }
  61.     );
  62.  
  63.     const src = new BABYLON.Texture("textures/ground.jpg", scene);
  64.     const dest = BABYLON.RawTexture.CreateRGBAStorageTexture(
  65.       null,
  66.       512,
  67.       512,
  68.       scene,
  69.       false,
  70.       false
  71.     );
  72.  
  73.     cs1.setTexture("src", src);
  74.     cs1.setStorageTexture("dest", dest);
  75.  
  76.     cs1
  77.       .dispatchWhenReady(dest.getSize().width, dest.getSize().height, 1)
  78.       .then(() => {
  79.         dest.readPixels().then((data) => {
  80.           //console.log(data);
  81.         });
  82.       });
  83.  
  84.     const mat = new BABYLON.StandardMaterial("mat", scene);
  85.     mat.diffuseTexture = dest;
  86.  
  87.     ground.material = mat;
  88.  
  89.     // -------- COMPUTE 2 -------------------------
  90.     //
  91.     const cs2 = new BABYLON.ComputeShader(
  92.       "myCompute2",
  93.       engine,
  94.       { computeSource: clearTextureComputeShader },
  95.       {
  96.         bindingsMapping: {
  97.           tbuf: { group: 0, binding: 0 },
  98.           params: { group: 0, binding: 1 },
  99.         },
  100.       }
  101.     );
  102.  
  103.     const dest2 = BABYLON.RawTexture.CreateRGBAStorageTexture(
  104.       null,
  105.       512,
  106.       512,
  107.       scene,
  108.       false,
  109.       false
  110.     );
  111.  
  112.     const uBuffer = new BABYLON.UniformBuffer(engine);
  113.  
  114.     uBuffer.updateColor4("color", new BABYLON.Color3(1, 0.6, 0.8), 1);
  115.     uBuffer.update();
  116.  
  117.     cs2.setStorageTexture("tbuf", dest2);
  118.     cs2.setUniformBuffer("params", uBuffer);
  119.  
  120.     cs2.dispatchWhenReady(dest2.getSize().width, dest2.getSize().height, 1);
  121.  
  122.     const mat2 = new BABYLON.StandardMaterial("mat2", scene);
  123.     mat2.diffuseTexture = dest2;
  124.  
  125.     sphere.material = mat2;
  126.  
  127.     // -------- COMPUTE 3 -------------------------
  128.     //
  129.     const cs3 = new BABYLON.ComputeShader(
  130.       "myCompute3",
  131.       engine,
  132.       { computeSource: matrixMulComputeShader },
  133.       {
  134.         bindingsMapping: {
  135.           firstMatrix: { group: 0, binding: 0 },
  136.           secondMatrix: { group: 0, binding: 1 },
  137.           resultMatrix: { group: 0, binding: 2 },
  138.         },
  139.       }
  140.     );
  141.  
  142.     const firstMatrix = new Float32Array([
  143.       2 /* rows */, 4 /* columns */, 1, 2, 3, 4, 5, 6, 7, 8,
  144.     ]);
  145.  
  146.     const bufferFirstMatrix = new BABYLON.StorageBuffer(
  147.       engine,
  148.       firstMatrix.byteLength
  149.     );
  150.     bufferFirstMatrix.update(firstMatrix);
  151.  
  152.     const secondMatrix = new Float32Array([
  153.       4 /* rows */, 2 /* columns */, 1, 2, 3, 4, 5, 6, 7, 8,
  154.     ]);
  155.  
  156.     const bufferSecondMatrix = new BABYLON.StorageBuffer(
  157.       engine,
  158.       secondMatrix.byteLength
  159.     );
  160.     bufferSecondMatrix.update(secondMatrix);
  161.  
  162.     const bufferResultMatrix = new BABYLON.StorageBuffer(
  163.       engine,
  164.       Float32Array.BYTES_PER_ELEMENT * (2 + firstMatrix[0] * secondMatrix[1])
  165.     );
  166.  
  167.     cs3.setStorageBuffer("firstMatrix", bufferFirstMatrix);
  168.     cs3.setStorageBuffer("secondMatrix", bufferSecondMatrix);
  169.     cs3.setStorageBuffer("resultMatrix", bufferResultMatrix);
  170.  
  171.     cs3.dispatchWhenReady(firstMatrix[0], secondMatrix[1]).then(() => {
  172.       bufferResultMatrix.read().then((res) => {
  173.         // we know the result buffer contains floats
  174.         const resFloats = new Float32Array(res.buffer);
  175.         console.log(resFloats);
  176.       });
  177.     });
  178.  
  179.     return scene;
  180.   };
  181.  
  182.   function checkComputeShadersSupported(engine, scene) {
  183.     const supportCS = engine.getCaps().supportComputeShaders;
  184.  
  185.     if (supportCS) {
  186.       return true;
  187.     }
  188.  
  189.     var panel = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI(
  190.       "UI",
  191.       true,
  192.       scene
  193.     );
  194.  
  195.     const textNOk =
  196.       "**Use WebGPU to watch this demo which requires compute shaders support. To enable WebGPU please use Edge Canary or Chrome canary. Also, select the WebGPU engine from the top right drop down menu.**";
  197.  
  198.     var info = new BABYLON.GUI.TextBlock();
  199.     info.text = textNOk;
  200.     info.width = "100%";
  201.     info.paddingLeft = "5px";
  202.     info.paddingRight = "5px";
  203.     info.textHorizontalAlignment =
  204.       BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
  205.     info.textVerticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
  206.     info.color = supportCS ? "green" : "red";
  207.     info.fontSize = supportCS ? "18px" : "24px";
  208.     info.fontStyle = supportCS ? "" : "bold";
  209.     info.textWrapping = true;
  210.     panel.addControl(info);
  211.  
  212.     return false;
  213.   }
  214.  
  215.   const clearTextureComputeShader = `
  216.             @group(0) @binding(0) var tbuf : texture_storage_2d<rgba8unorm,write>;
  217.        
  218.             struct Params {
  219.                 color : vec4<f32>;
  220.             };
  221.             @group(0) @binding(1) var<uniform> params : Params;
  222.        
  223.             @stage(compute) @workgroup_size(1, 1, 1)
  224.        
  225.             fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
  226.                 textureStore(tbuf, vec2<i32>(global_id.xy), params.color);
  227.             }
  228.         `;
  229.  
  230.   const copyTextureComputeShader = `
  231.             @group(0) @binding(0) var dest : texture_storage_2d<rgba8unorm,write>;
  232.             @group(0) @binding(1) var samplerSrc : sampler;
  233.             @group(0) @binding(2) var src : texture_2d<f32>;
  234.        
  235.             @stage(compute) @workgroup_size(1, 1, 1)
  236.        
  237.             fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
  238.                 let dims : vec2<f32> = vec2<f32>(textureDimensions(src, 0));
  239.                 let pix : vec4<f32> = textureSampleLevel(src, samplerSrc, vec2<f32>(global_id.xy) / dims, 0.0);
  240.                 textureStore(dest, vec2<i32>(global_id.xy), pix);
  241.             }
  242.         `;
  243.  
  244.   const matrixMulComputeShader = `
  245.             struct Matrix {
  246.               size : vec2<f32>;
  247.               numbers: array<f32>;
  248.             };
  249.        
  250.             @group(0) @binding(0) var<storage,read> firstMatrix : Matrix;
  251.             @group(0) @binding(1) var<storage,read> secondMatrix : Matrix;
  252.             @group(0) @binding(2) var<storage,write> resultMatrix : Matrix;
  253.        
  254.             @stage(compute) @workgroup_size(1, 1, 1)
  255.             fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
  256.               resultMatrix.size = vec2<f32>(firstMatrix.size.x, secondMatrix.size.y);
  257.        
  258.               let resultCell : vec2<u32> = vec2<u32>(global_id.x, global_id.y);
  259.               var result : f32 = 0.0;
  260.               for (var i : u32 = 0u; i < u32(firstMatrix.size.y); i = i + 1u) {
  261.                 let a : u32 = i + resultCell.x * u32(firstMatrix.size.y);
  262.                 let b : u32 = resultCell.y + i * u32(secondMatrix.size.y);
  263.                 result = result + firstMatrix.numbers[a] * secondMatrix.numbers[b];
  264.               }
  265.        
  266.               let index : u32 = resultCell.y + resultCell.x * u32(secondMatrix.size.y);
  267.               resultMatrix.numbers[index] = result;
  268.             }
  269.         `;
  270. })();
  271.  
Advertisement
Add Comment
Please, Sign In to add comment