webgpu实现粒子颗粒化飘动动画效果代码

代码语言:html

所属分类:粒子

代码描述:webgpu实现粒子颗粒化飘动动画效果代码

代码标签: webgpu 粒子 颗粒化 飘动 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">

  
  
  
<style>
html,body {
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
}
</style>


  
  
</head>

<body translate="no">
  <canvas></canvas>
  
      <script >
console.clear();

if (!navigator.gpu) {
  console.error("WebGPU not supported in this browser.");
  throw new Error("WebGPU not supported.");
}

async function initWebGPU() {
  const canvas = document.querySelector('canvas');
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();
  const context = canvas.getContext('webgpu');

  // Resize canvas to fit the window
  const dpi = 2;
  const resizeCanvas = () => {
    canvas.width = window.innerWidth * dpi;
    canvas.height = window.innerHeight * dpi;
  };
  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);

  // Configure the canvas context
  const format = navigator.gpu.getPreferredCanvasFormat();
  context.configure({
    device: device,
    format: format,
    alphaMode: 'premultiplied' });


  return { device, context, format };
}
function createRenderLoop(device, context, positionBuffer, velocityBuffer, timeBuffer) {
  const shaderModule = createShaderModule(device);
  const pipeline = createRenderPipeline(device, shaderModule);

  const { computePipeline, bindGroup } = initComputePass(device, positionBuffer, velocityBuffer, timeBuffer);

  const renderBindGroupLayout = pipeline.getBindGroupLayout(0);
  const renderBindGroup = device.createBindGroup({
    layout: renderBindGroupLayout,
    entries: [{ binding: 0, resource: { buffer: positionBuffer } }] });


  let startTime = performance.now();

  const render = () => {
    const elapsedTime = (performance.now() - startTime) * .0001;
    device.queue.writeBuffer(timeBuffer, 0, new Float32Array([elapsedTime]));

    const commandEncoder = device.createCommandEncoder();

    // Compute Pass
    const computePass = commandEncoder.beginComputePass();
    computePass.setPipeline(computePipeline);
    computePass.setBindGroup(0, bindGroup);
    computePass.dispatchWorkgroups(Math.ceil(NUM_PARTICLES / 64));
    computePass.end();

    // Render Pass
    const textureView = context.getCurrentTexture().createView();
    const renderPassDescriptor = {
      colorAttachments: [{
        view: textureView,
        clearValue: { r: 0, g: 0, b: 0, a: 1 },
        loadOp: 'clear',
        storeOp: 'store' }] };



    const renderPass = commandEncoder.beginRenderPass(renderPassDescriptor);
    renderPass.setPipeline(pipeline);
    renderPass.setBindGroup(0, renderBindGroup);
    renderPass.draw(NUM_PARTICLES);
    renderPass.end();

    device.queue.submit([commandEncoder.finish()]);
    requestAnimationFrame(render);
  };

  render();
}


const NUM_PARTICLES = 2000000;
function generateParticleData() {
  const positions = new Float32Array(NUM_PARTICLES * 3);
  const velocities = new Float32Array(NUM_PARTICLES * 3);

  for (let i = 0; i < NUM_PARTICLES; i++) {
    // Random position in a cube [-1, 1]
    positions[i * 3 + 0] = Math.random() * 1 - .5; // x
    positions[i * 3 + 1] = Math.random() * 1 - .5; // y
    positions[i * 3 + 2] = Math.random() * 1 - .5; // z

    // Random velocity in range [-0.1, 0.1]
    velocities[i * 3 + 0] = Math.random() * 0.2 - 0.1; // vx
    velocities[i * 3 + 1] = Math.random() * 0.2 - 0.1; // vy
    velocities[i * 3 + 2] = Math.random() * 0.2 - 0.1; // vz
  }

  return { positions, velocities };
}
function createParticleBuffers(device, positions, velocities) {
  // Create position buffer
  const positionBuffer = device.createBuffer({
    size: positions.byteLength,
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE,
    mappedAtCreation: true });

  new Float32Array(positionBuffer.getMappedRange()).set(positions);
  positionBuffer.unmap();

  // Create velocity buffer
  const velocityBuffer = device.createBuffer({
    size: velocities.byteLength,
    usage: GPUBufferUsage.STORAGE,
    mappedAtCreation: true });

  new Float32Array(velocityBuffer.getMappedRange()).set(velocities);
  velocityBuffer.unmap();

  return { positionBuffer, velocityBuffer };
}
async function initParticleSystem(device) {
  const { positions, velocities } = generateParticleData();
  const buffe.........完整代码请登录后点击上方下载按钮下载查看

网友评论0