3d 深度贴图,背面剔除,各个面有独立颜色

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>てst</title>
</head>

<body>
  <!-- canvas:用来展示WebGPU渲染的结果 -->
  <canvas id="webgpu" width="500" height="500"></canvas>
  translationx:<input type="range" min="0" max="500" step="0.1" name="translationx" value="230.2" /><br>
  translationy:<input type="range" min="0" max="500" step="0.1" name="translationy" value="230.2" /><br>
  rotationx:<input type="range" min="0" max="360" step="0.1" name="rotationx" value="0" /><br>
  rotationy:<input type="range" min="0" max="360" step="0.1" name="rotationy" value="0" /><br>
  rotationz:<input type="range" min="0" max="360" step="0.1" name="rotationz" value="0" /><br>
  scalex:<input type="range" min="-5" max="5" step="0.1" name="scalex" value="1.1" /><br>
  scaley:<input type="range" min="-5" max="5" step="0.1" name="scaley" value="1.1" /><br>

  <script type="module">
    //"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="D:\angular\webgpu\n" --disable-site-isolation-trials

    import * as glMatrix from './dist/esm/index.js';

   function createFVertices() {
  const positions = [
    // left column
    0, 0, 0,
    30, 0, 0,
    0, 150, 0,
    30, 150, 0,

    // top rung
    30, 0, 0,
    100, 0, 0,
    30, 30, 0,
    100, 30, 0,

    // middle rung
    30, 60, 0,
    70, 60, 0,
    30, 90, 0,
    70, 90, 0,

    // left column back
    0, 0, 30,
    30, 0, 30,
    0, 150, 30,
    30, 150, 30,

    // top rung back
    30, 0, 30,
    100, 0, 30,
    30, 30, 30,
    100, 30, 30,

    // middle rung back
    30, 60, 30,
    70, 60, 30,
    30, 90, 30,
    70, 90, 30,
  ];

  const indices = [
    // front
    0,  1,  2,    2,  1,  3,  // left column
    4,  5,  6,    6,  5,  7,  // top rung
    8,  9, 10,   10,  9, 11,  // middle rung

    // back
    12,  13,  14,   14, 13, 15,  // left column back
    16,  17,  18,   18, 17, 19,  // top rung back
    20,  21,  22,   22, 21, 23,  // middle rung back

    0, 5, 12,   12, 5, 17,   // top
    5, 7, 17,   17, 7, 19,   // top rung right
    6, 7, 18,   18, 7, 19,   // top rung bottom
    6, 8, 18,   18, 8, 20,   // between top and middle rung
    8, 9, 20,   20, 9, 21,   // middle rung top
    9, 11, 21,  21, 11, 23,  // middle rung right
    10, 11, 22, 22, 11, 23,  // middle rung bottom
    10, 3, 22,  22, 3, 15,   // stem right
    2, 3, 14,   14, 3, 15,   // bottom
    0, 2, 12,   12, 2, 14,   // left
  ];

  const quadColors = [
      200,  70, 120,  // left column front
      200,  70, 120,  // top rung front
      200,  70, 120,  // middle rung front

       80,  70, 200,  // left column back
       80,  70, 200,  // top rung back
       80,  70, 200,  // middle rung back

       70, 200, 210,  // top
      160, 160, 220,  // top rung right
       90, 130, 110,  // top rung bottom
      200, 200,  70,  // between top and middle rung
      210, 100,  70,  // middle rung top
      210, 160,  70,  // middle rung right
       70, 180, 210,  // middle rung bottom
      100,  70, 210,  // stem right
       76, 210, 100,  // bottom
      140, 210,  80,  // left
  ];

  const numVertices = indices.length;
  const vertexData = new Float32Array(numVertices * 4); // xyz + color
  vertexData.fill(-1);
  const colorData = new Uint8Array(vertexData.buffer);
  for (let i = 0; i < indices.length; ++i) {
    const positionNdx = indices[i] * 3;
    const position = positions.slice(positionNdx, positionNdx + 3);
    vertexData.set(position, i * 4);

    const quadNdx = (i / 6 | 0) * 3;
    const color = quadColors.slice(quadNdx, quadNdx + 3);
    colorData.set(color, i * 16 + 12);
    colorData[i * 16 + 15] = 255;
  }

  return {
    vertexData,
    numVertices,
  };
}
    

    async function main() {
      const adapter = await navigator.gpu?.requestAdapter();
      const device = await adapter?.requestDevice();
      if (!device) {
        fail('need a browser that supports WebGPU');
        return;
      }

      // Get a WebGPU context from the canvas and configure it
      const canvas = document.querySelector('canvas');
      const context = canvas.getContext('webgpu');
      const presentationFormat = navigator.gpu.getPreferredCanvasFormat();

      context.configure({
        device,
        format: presentationFormat,
        alphaMode: 'premultiplied',
      });

      const module = device.createShaderModule({
        code: `
        struct Uniforms {
        matrix: mat4x4f,
      };

      struct Vertex {
        @location(0) position: vec4f,
        @location(1) color: vec4f,
      };

      struct VSOutput {
        @builtin(position) position: vec4f,
        @location(0) color: vec4f,
      };

      @group(0) @binding(0) var<uniform> uni: Uniforms;

      @vertex fn vs(vert: Vertex) -> VSOutput {
        var vsOut: VSOutput;
        vsOut.position = uni.matrix * vert.position;
        vsOut.color = vert.color;
        return vsOut;
      }

      @fragment fn fs(vsOut: VSOutput) -> @location(0) vec4f {
        return vsOut.color;
      }
    `
      });

      const pipeline = device.createRenderPipeline({
        label: 'just 2d position',
        layout: 'auto',
        vertex: {
          module,
          entryPoint: 'vs',
          buffers: [
            {
              arrayStride: (4) * 4, // (2) floats, 4 bytes each
              attributes: [
                { shaderLocation: 0, offset: 0, format: 'float32x3' },  // position
                {shaderLocation: 1, offset: 12, format: 'unorm8x4'},  // 顏色
              ],
            },
          ],
        },
        primitive: {
      cullMode: 'back',//front
    },
        fragment: {
          module,
          entryPoint: 'fs',
          targets: [{ format: presentationFormat }],
        },
         depthStencil: {
      depthWriteEnabled: true,
      depthCompare: 'less',
      format: 'depth24plus',
    },
      });

      // color, resolution, padding, matrix
      const uniformBufferSize = (16) * 4;
      const uniformBuffer = device.createBuffer({
        label: 'uniforms',
        size: uniformBufferSize,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
      });

      const uniformValues = new Float32Array(uniformBufferSize / 4);

      // offsets to the various uniform values in float32 indices
      //const kColorOffset = 0;
       
      const kMatrixOffset = 0;

     // const colorValue = uniformValues.subarray(kColorOffset, kColorOffset + 4);
      const matrixValue = uniformValues.subarray(kMatrixOffset, kMatrixOffset + 16);

      // The color will not change so let's set it once at init time
     // colorValue.set([Math.random(), Math.random(), Math.random(), 1]);

      
     const { vertexData, numVertices } = createFVertices();
      const vertexBuffer = device.createBuffer({
        label: 'vertex buffer vertices',
        size: vertexData.byteLength,
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
      });
      device.queue.writeBuffer(vertexBuffer, 0, vertexData);

      const bindGroup = device.createBindGroup({
        label: 'bind group for object',
        layout: pipeline.getBindGroupLayout(0),
        entries: [
          { binding: 0, resource: { buffer: uniformBuffer } },
        ],
      });

      const renderPassDescriptor = {
        label: 'our basic canvas renderPass',
        colorAttachments: [
          {
            // view: <- to be filled out when we render
            loadOp: 'clear',
            storeOp: 'store',
          },
        ],
        depthStencilAttachment: {
      // view: <- 渲染時填寫
      depthClearValue: 1.0,
      depthLoadOp: 'clear',
      depthStoreOp: 'store',
    },
      };
 let depthTexture;
      function render() {

// Get the current texture from the canvas context and
    // set it as the texture to render to.
    const canvasTexture = context.getCurrentTexture();
    renderPassDescriptor.colorAttachments[0].view = canvasTexture.createView();

    // If we don't have a depth texture OR if its size is different
    // from the canvasTexture when make a new depth texture
    if (!depthTexture ||
        depthTexture.width !== canvasTexture.width ||
        depthTexture.height !== canvasTexture.height) {
      if (depthTexture) {
        depthTexture.destroy();
      }
      depthTexture = device.createTexture({
        size: [canvasTexture.width, canvasTexture.height],
        format: 'depth24plus',
        usage: GPUTextureUsage.RENDER_ATTACHMENT,
      });
    }
    renderPassDescriptor.depthStencilAttachment.view = depthTexture.createView();

        const encoder = device.createCommandEncoder();
        const pass = encoder.beginRenderPass(renderPassDescriptor);
        pass.setPipeline(pipeline);
        pass.setVertexBuffer(0, vertexBuffer);

        let translationx = document
          .querySelector('input[name="translationx"]')
          .value;
        let translationy = document
          .querySelector('input[name="translationy"]')
          .value;
        let rotationx = document
          .querySelector('input[name="rotationx"]')
          .value;
        rotationx = rotationx * Math.PI / 180;
        
        let rotationy = document
          .querySelector('input[name="rotationy"]')
          .value;
        rotationy = rotationy * Math.PI / 180;
        
        let rotationz = document
          .querySelector('input[name="rotationz"]')
          .value;
        rotationz = rotationz * Math.PI / 180;

        let scalex = document
          .querySelector('input[name="scalex"]')
          .value;
        let scaley = document
          .querySelector('input[name="scaley"]')
          .value;

        let translationMatrix = glMatrix.mat4.create();
        glMatrix.mat4.translate(translationMatrix, translationMatrix, glMatrix.vec3    .fromValues(translationx, translationy,1));

        let rotationMatrix = glMatrix.mat4.create();
       // glMatrix.mat4.rotate(rotationMatrix, rotationMatrix, 1, glMatrix.vec3.fromValues(Math.sin(rotation), Math.cos(rotation), 0));
        //glMatrix.mat4.rotate(rotationMatrix, rotationMatrix, rotation);

        glMatrix.mat4.rotateX(rotationMatrix, rotationMatrix, rotationx);
        glMatrix.mat4.rotateY(rotationMatrix, rotationMatrix, rotationy);
        glMatrix.mat4.rotateZ(rotationMatrix, rotationMatrix, rotationz);

        let scaleMatrix = glMatrix.mat4.create();
        glMatrix.mat4.scale(scaleMatrix, scaleMatrix, [scalex, scaley, 1]);

        // make a matrix that will move the origin of the 'F' to its center.
        // const moveOriginMatrix = mat3.translation([-50, -75]);
        let moveOriginMatrix = glMatrix.mat4.create();
        //glMatrix.mat4.translate(moveOriginMatrix, moveOriginMatrix, glMatrix.vec2.fromValues(-50, -70));

//-------------
 //固定相机,正交投影
 //  const aspect = Math.abs(canvas.width / canvas.height);
  let projectionMatrix = glMatrix.mat4.create();
 // glMatrix.mat4.perspective(projectionMatrix, (2 * Math.PI) / 5, aspect, 1, 100.0);
  // glMatrix.mat4.projection(projectionMatrix,400,canvas.clientWidth, canvas.clientHeight);
   glMatrix.mat4.ortho(projectionMatrix,0,canvas.clientWidth, 0,canvas.clientHeight,400,-400);
   
   /*
   mat4.ortho(
        0,                   // 左边
        canvas.clientWidth,  // 正确的
        canvas.clientHeight, // 底部
        0,                   // 顶部
        400,                 // 靠近
        -400,                // 远的
        matrixValue,         // 夏令时
    ); 
    */
//-------------
        let matrix = glMatrix.mat4.create();
        //glMatrix.mat4.multiply(matrix, translationMatrix, rotationMatrix);
        glMatrix.mat4.multiply(matrix,projectionMatrix, translationMatrix);
        glMatrix.mat4.multiply(matrix, matrix, rotationMatrix);
        glMatrix.mat4.multiply(matrix, matrix, scaleMatrix);

        // matrix = mat3.multiply(matrix, moveOriginMatrix);
        glMatrix.mat4.multiply(matrix, matrix, moveOriginMatrix);

/*
        console.log('matrix:' + matrix);
        console.log('matrix0-3:' + matrix.slice(0, 3));
        console.log('matrixValue:' + matrixValue);
*/
        // Set the uniform values in our JavaScript side Float32Array
       // resolutionValue.set([canvas.width, canvas.height]);
        
     /*
        matrixValue.set([
          ...matrix.slice(0, 3), 0,
          ...matrix.slice(3, 6), 0,
          ...matrix.slice(6, 9), 0,
        ]);
*/
 //console.log(matrix) 
  matrixValue.set(matrix);

        // upload the uniform values to the uniform buffer
        device.queue.writeBuffer(uniformBuffer, 0, uniformValues);

        pass.setBindGroup(0, bindGroup);
        // pass.drawIndexed(numVertices);
        pass.draw(numVertices);
        //pass.drawIndexed(numVertices);
        pass.end();

        const commandBuffer = encoder.finish();
        device.queue.submit([commandBuffer]);
      }

      //-----------------
      document
        .querySelector('input[name="translationx"]')
        .addEventListener("input", (e) => {
          render();
        });

      document
        .querySelector('input[name="translationy"]')
        .addEventListener("input", (e) => {
          render();
        });
      document
        .querySelector('input[name="rotationx"]')
        .addEventListener("input", (e) => {
          render();
        });
        document
        .querySelector('input[name="rotationy"]')
        .addEventListener("input", (e) => {
          render();
        });
        document
        .querySelector('input[name="rotationz"]')
        .addEventListener("input", (e) => {
          render();
        });
      document
        .querySelector('input[name="scalex"]')
        .addEventListener("input", (e) => {
          render();
        });
      document
        .querySelector('input[name="scaley"]')
        .addEventListener("input", (e) => {
          render();
        });

      const observer = new ResizeObserver(entries => {
        for (const entry of entries) {
          const canvas = entry.target;
          const width = entry.contentBoxSize[0].inlineSize;
          const height = entry.contentBoxSize[0].blockSize;
          canvas.width = Math.max(1, Math.min(width, device.limits.maxTextureDimension2D));
          canvas.height = Math.max(1, Math.min(height, device.limits.maxTextureDimension2D));
          // re-render
          render();
        }
      });
      observer.observe(canvas);
    }

    function fail(msg) {
      alert(msg);
    }

    main();
  </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值