一个旋转cube,没有用lookat

本文介绍了如何在现代浏览器中利用WebGPUAPI创建一个3D立方体渲染示例,包括设置uniformbuffer对象(ubo)、顶点数据、WebGLshaders以及GPU矩阵变换,展示了如何进行渲染管线配置和图形效果控制。
摘要由CSDN通过智能技术生成

<!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>
    <script type="module">
       
 //chrome setting:
 //"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="D:\angular\webgpu\n" --disable-site-isolation-trials
 //
 
 //1,增加一个uniform buffer object(简称为ubo),
 //用于传输“model矩阵 乘以 view矩阵 乘以 projection矩阵”的结果矩阵(简称为mvp矩阵),并在每帧被更新
//2.设置顶点
//3.开启面剔除
//4.开启深度测试
 
        // 配置WebGPU上下文
        const adapter = await navigator.gpu.requestAdapter();
        const device = await adapter.requestDevice();
        const canvas = document.getElementById('webgpu');
        const context = canvas.getContext('webgpu');
        const format = navigator.gpu.getPreferredCanvasFormat();
        context.configure({
            device: device,
            format: format,
        });
 
 
     const cubeVertexArray2 = new Float32Array([
  // float4 position, float4 color, float2 uv,
  1, -1, 1, 1,   1, 0, 1, 1,  1, 1,
  -1, -1, 1, 1,  0, 0, 1, 1,  0, 1,
  -1, -1, -1, 1, 0, 0, 0, 1,  0, 0,
  1, -1, -1, 1,  1, 0, 0, 1,  1, 0,
  1, -1, 1, 1,   1, 0, 1, 1,  1, 1,
  -1, -1, -1, 1, 0, 0, 0, 1,  0, 0,

  1, 1, 1, 1,    1, 1, 1, 1,  1, 1,
  1, -1, 1, 1,   1, 0, 1, 1,  0, 1,
  1, -1, -1, 1,  1, 0, 0, 1,  0, 0,
  1, 1, -1, 1,   1, 1, 0, 1,  1, 0,
  1, 1, 1, 1,    1, 1, 1, 1,  1, 1,
  1, -1, -1, 1,  1, 0, 0, 1,  0, 0,

  -1, 1, 1, 1,   0, 1, 1, 1,  1, 1,
  1, 1, 1, 1,    1, 1, 1, 1,  0, 1,
  1, 1, -1, 1,   1, 1, 0, 1,  0, 0,
  -1, 1, -1, 1,  0, 1, 0, 1,  1, 0,
  -1, 1, 1, 1,   0, 1, 1, 1,  1, 1,
  1, 1, -1, 1,   1, 1, 0, 1,  0, 0,

  -1, -1, 1, 1,  0, 0, 1, 1,  1, 1,
  -1, 1, 1, 1,   0, 1, 1, 1,  0, 1,
  -1, 1, -1, 1,  0, 1, 0, 1,  0, 0,
  -1, -1, -1, 1, 0, 0, 0, 1,  1, 0,
  -1, -1, 1, 1,  0, 0, 1, 1,  1, 1,
  -1, 1, -1, 1,  0, 1, 0, 1,  0, 0,

  1, 1, 1, 1,    1, 1, 1, 1,  1, 1,
  -1, 1, 1, 1,   0, 1, 1, 1,  0, 1,
  -1, -1, 1, 1,  0, 0, 1, 1,  0, 0,
  -1, -1, 1, 1,  0, 0, 1, 1,  0, 0,
  1, -1, 1, 1,   1, 0, 1, 1,  1, 0,
  1, 1, 1, 1,    1, 1, 1, 1,  1, 1,

  1, -1, -1, 1,  1, 0, 0, 1,  1, 1,
  -1, -1, -1, 1, 0, 0, 0, 1,  0, 1,
  -1, 1, -1, 1,  0, 1, 0, 1,  0, 0,
  1, 1, -1, 1,   1, 1, 0, 1,  1, 0,
  1, -1, -1, 1,  1, 0, 0, 1,  1, 1,
  -1, 1, -1, 1,  0, 1, 0, 1,  0, 0,
]);
        
 //-------设置顶点--------------------------
//引入gl-matrix.js库
 import * as glMatrix from './dist/esm/index.js';

  // 定点缓冲区
  const vertexBuffer = device.createBuffer({
    size: cubeVertexArray2.byteLength, //顶点数据的字节长度
    //usage设置该缓冲区的用途(作为顶点缓冲区|可以写入顶点数据)
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
  });
 
  // 将顶点信息写入缓冲器
  device.queue.writeBuffer(vertexBuffer, 0, cubeVertexArray2);
  

//------------wsgl代码-------------------  
  const module = device.createShaderModule({
    label: 'triangle shaders with uniforms',
    code: `

struct Uniforms {
  modelViewProjectionMatrix : mat4x4f//这里不能用分号
};

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

struct VertexOutput {
  @builtin(position) Position : vec4f,
  @location(0) fragUV : vec2f,
  @location(1) fragPosition: vec4f
};

@vertex
fn vs(@location(0) position : vec4f,@location(1) uv : vec2f) -> VertexOutput {
  var output : VertexOutput;
  output.Position =  uniforms.modelViewProjectionMatrix * position;
  output.fragUV = uv;
  output.fragPosition = 0.5 * (position + vec4f(1.0, 1.0, 1.0, 1.0));
  return output;
}

@fragment 
fn fs(@location(0) fragUV: vec2<f32>,@location(1) fragPosition: vec4<f32>) -> @location(0) vec4<f32> {
  return fragPosition;
}

`,
  });
 
 let cubePositionOffset=0;
 let cubeUVOffset=4*8;
 let cubeVertexSize=4*10;
 const pipeline = device.createRenderPipeline({
 layout: "auto",
    vertex: {
      module: module ,
      entryPoint: 'vs',
      buffers: [ // 为顶点着色器配置Buffer
        {
          arrayStride: cubeVertexSize,
          attributes: [
            {
              // position
              shaderLocation: 0,
              offset: cubePositionOffset,
              format: 'float32x4',
            },
            {
              // uv
              shaderLocation: 1,
              offset: cubeUVOffset,
              format: 'float32x2',
            },
          ],
        },
      ],
    },
    fragment: {
      module: module ,
      entryPoint: 'fs',
      targets: [
        {
          format: format,
        },
      ],
    },
    primitive: {
      topology: 'triangle-list',

      // Backface culling since the cube is solid piece of geometry.
      // Faces pointing away from the camera will be occluded by faces
      // pointing toward the camera.

//3.开启背面面剔除

      cullMode: 'back',
    },
    //multisample: {
    //  count: 4
    //},

    // Enable depth testing so that the fragment closest to the camera
    // is rendered in front.
    
    //4.开启深度测试
    depthStencil: {
      depthWriteEnabled: true,
      depthCompare: 'less',
      format: 'depth24plus',
    },
  });

 
const uniformBufferSize = 4 * 16; // 4x4 matrix
  const uniformBuffer = device.createBuffer({
    size: uniformBufferSize,
    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
  });

const uniformBindGroup = device.createBindGroup({
    layout: pipeline.getBindGroupLayout(0),
    entries: [
      {
        binding: 0,
        resource: {
          buffer: uniformBuffer,
        },
      },
    ],
  });
  
 const depthTexture = device.createTexture({
    size: {
      width: canvas.width,
      height: canvas.height,
    },
    format: "depth24plus",
    //sampleCount: 4,
    usage: GPUTextureUsage.RENDER_ATTACHMENT
  });
 
 const renderPassDescriptor = {
    colorAttachments: [
      {
       // view: context.getCurrentTexture().createView(), // Assigned later
loadOp: 'clear',
        loadValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
       storeOp: 'store',
      },
    ],
    depthStencilAttachment: {
      view: depthTexture.createView(),
depthStoreOp: 'store',
depthClearValue: 1.0,
      depthLoadOp: "clear",
      depthLoadValue: 1.0,
     // depthStoreOp: 'store',
     // stencilLoadValue: 0,
      //stencilStoreOp: 'store',
    },
  };
  
  //固定相机,透视投影
   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);
 
   //计算mvp矩阵
  function getTransformationMatrix() {
  
  //顺序:平移--》旋转--》缩放
    let viewMatrix = glMatrix.mat4.create();
    glMatrix.mat4.translate(viewMatrix, viewMatrix, glMatrix.vec3.fromValues(0, 0, -5));
    let now = Date.now() / 1000;
    glMatrix.mat4.rotate(viewMatrix, viewMatrix, 1, glMatrix.vec3.fromValues(Math.sin(now), Math.cos(now), 0));

    let modelViewProjectionMatrix = glMatrix.mat4.create();
    //顺序:透视投影 x 旋转矩阵
    glMatrix.mat4.multiply(modelViewProjectionMatrix, projectionMatrix, viewMatrix);

    return modelViewProjectionMatrix;
  }
  //------------------


  function frame() {
    const transformationMatrix = getTransformationMatrix();
    device.queue.writeBuffer(
      uniformBuffer,
      0,
      transformationMatrix.buffer,
      transformationMatrix.byteOffset,
      transformationMatrix.byteLength
    );
    
    //必须在这里设置texture,否则保存
 renderPassDescriptor.colorAttachments[0].view = context
      .getCurrentTexture()
      .createView();

    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(0, uniformBindGroup);
    passEncoder.setVertexBuffer(0, vertexBuffer);
    passEncoder.draw(36, 1, 0, 0);
    passEncoder.end();
    device.queue.submit([commandEncoder.finish()]);
    requestAnimationFrame(frame);
  };
frame();
    </script>
</body>
 
</html>

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个比较复杂的问题,需要使用Java的3D图形库来实现。以下是一个简单的示例代码,可以实现一个旋转的魔方模型: ```java import javax.media.j3d.*; import javax.vecmath.*; public class RubiksCube extends Shape3D { private static final int NUM_FACES = 6; private static final int NUM_CUBES_PER_SIDE = 3; private static final float CUBE_SIZE = 0.5f; private static final float FACE_SIZE = CUBE_SIZE * NUM_CUBES_PER_SIDE; private Transform3D rotationTransform; public RubiksCube() { // 创建一个立方体数组,表示魔方的所有小立方体 Box[][][] cubes = new Box[NUM_CUBES_PER_SIDE][NUM_CUBES_PER_SIDE][NUM_CUBES_PER_SIDE]; // 创建每个小立方体并将其添加到数组中 for (int i = 0; i < NUM_CUBES_PER_SIDE; i++) { for (int j = 0; j < NUM_CUBES_PER_SIDE; j++) { for (int k = 0; k < NUM_CUBES_PER_SIDE; k++) { Vector3f translation = new Vector3f( (i - 1) * CUBE_SIZE, (j - 1) * CUBE_SIZE, (k - 1) * CUBE_SIZE); cubes[i][j][k] = new Box(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE, createAppearance()); Transform3D translationTransform = new Transform3D(); translationTransform.setTranslation(translation); TransformGroup cubeTransformGroup = new TransformGroup(); cubeTransformGroup.setTransform(translationTransform); cubeTransformGroup.addChild(cubes[i][j][k]); addChild(cubeTransformGroup); } } } // 创建旋转变换 rotationTransform = new Transform3D(); rotationTransform.rotY(Math.PI / 4.0); } // 创建外观 private Appearance createAppearance() { Appearance appearance = new Appearance(); // 设置材质属性 Material material = new Material(); material.setDiffuseColor(1.0f, 1.0f, 1.0f); material.setShininess(64.0f); appearance.setMaterial(material); return appearance; } // 旋转魔方 public void rotate() { Transform3D currentTransform = new Transform3D(); getTransform(currentTransform); currentTransform.mul(rotationTransform); setTransform(currentTransform); } } ``` 这个代码创建了一个 `RubiksCube` 类,它继承自 `Shape3D`。它包含了一个立方体数组,每个小立方体都是一个 `Box` 实例,它们被组合成一个完整的魔方模型。 在构造函数中,我们创建了每个小立方体,并将它们添加到立方体数组中。然后我们将每个小立方体包装在一个 `TransformGroup` 中,这样我们可以对整个魔方模型进行变换。 最后,我们创建了一个旋转变换 `rotationTransform`,并在 `rotate()` 方法中应用它,以旋转整个魔方模型。你可以在你的程序中使用这个类来创建一个3D的旋转鸡块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值