Three.js中文网 Three.js中文网
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
Web3D系统课程视频
  • 1.WebGPU快速入门

  • 2. 3D几何变换数学基础

    • 1. 数学基础(平移、旋转、缩放矩阵)
    • 2. 模型矩阵
    • 3. gl-matrix数学计算库
    • 4. 顶点着色器矩阵变换
    • 5. WebGPU传递uniform数据
      • 6. gl-matrix生成顶点着色器的矩阵
      • 7. WebGPU动画(uniform旋转矩阵)
      • 8. 绕y轴旋转动画
      • 9. 片元的屏幕坐标
      • 10. 片元深度值、深度缓冲区
      • 11. WebGPU顶点数据插值计算
      • 12. 练习—顶点位置插值
      • 13. 顶点颜色数据插值计算
      • 14. 顶点位置、颜色数据共享缓冲区
      • 15. 练习-顶点颜色
      • 16. 结构体作为WGLSL函数参数
    • WebGPU教程
    • 2. 3D几何变换数学基础
    郭隆邦
    2023-05-19
    目录

    5. WebGPU传递uniform数据

    # WebGPU传递uniform数据

    前面给大家讲解过,通过JavaScript类型化数组创建顶点数据,然后把顶点数据传递给顶点着色器,本节课给大家讲解如何把uniform数据传递给顶点着色器或者片元着色器。

    比如上节课介绍的顶点着色器的缩放矩阵,是写在顶点着色器代码中的,你可以把shader代码中的缩放矩阵数据,放在JavaScript代码中,然后再传入到顶点着色器。

    # 顶点缓冲区知识点回顾

    把顶点数据在JavaScript代码中创建传入到顶点着色器中。

    //类型化数组表示顶点数据
    const vertexArray = new Float32Array([0.0, 0.0, 0.0,1.0, 0.0, 0.0,0.0, 1.0, 0.0,]);
    // 创建存储顶点数据的顶点缓冲区
    const vertexBuffer = device.createBuffer({
        size: vertexArray.byteLength,//顶点数据的字节长度
        //usage设置该缓冲区的用途
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
    });
    //把vertexArray里面的顶点数据写入到vertexBuffer对应的GPU显存缓冲区中
    device.queue.writeBuffer(vertexBuffer, 0, vertexArray);
    

    你参考前面入门案例关于顶点数据传递的讲解,来理解本节课uniform传递矩阵数据的传递。

    # 类型化数组表示缩放矩阵数据

    上节课讲解的,在顶点着色器中创建了一个缩放矩阵。

    @vertex
    fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> {
        // 创建一个缩放矩阵(沿着x、y分别缩放0.5倍)
        //0.5  0    0    0
        //0    0.5  0    0
        //0    0    1    0
        //0    0    0    1
        // 矩阵元素一列一列输入mat4x4<f32>()
        var S = mat4x4<f32>(0.5,0.0,0.0,0.0,  0.0,0.5,0.0,0.0,  0.0,0.0,1.0,0.0,  0.0,0.0,0.0,1.0);
    }
    

    缩放矩阵数据,从顶点着色器删除,写在JavaScript代码中。

     // 创建一个缩放矩阵(沿着x、y分别缩放0.5倍)
     //0.5  0    0    0
     //0    0.5  0    0
     //0    0    1    0
     //0    0    0    1
     const mat4Array = new Float32Array([
         // 矩阵元素一列一列输入作为类型化数组的参数
         0.5, 0.0, 0.0, 0.0, 
         0.0, 0.5, 0.0, 0.0, 
         0.0, 0.0, 1.0, 0.0, 
         0.0, 0.0, 0.0, 1.0
    ])
    

    对于这样一个需要传入到着色器中的矩阵数据(非顶点数据),你可以把他称为uniform数据。

    # 创建uniform数据的缓冲区

    创建uniform数据的缓冲区,和创建顶点缓冲区类似,都是使用.createBuffer(),其它的代码形式基本一样,注意参数属性usage的值,如果设置为GPUBufferUsage.VERTEX表示缓冲区用于存放顶点数据,GPUBufferUsage.UNIFORM表示缓冲区用于存放uniform数据(非顶点数据)。

    // 创建存储顶点数据的顶点缓冲区
    const vertexBuffer = device.createBuffer({
        size: vertexArray.byteLength,//顶点数据的字节长度
        //GPUBufferUsage.VERTEX表示缓冲区用于顶点数据
        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
    });
    
    // 在GPU显存上创建一个uniform数据缓冲区
    const mat4Buffer = device.createBuffer({
        size: mat4Array.byteLength,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    });
    

    # uniform数据写入到uniform缓冲区中

    niform数据写入到uniform缓冲区中,和前面顶点数据传入到顶点缓冲区中,使用的方法一样,都是device.queue.writeBuffer()。

    // mat4Array里面矩阵数据写入uniform缓冲区mat4Buffer
    device.queue.writeBuffer(mat4Buffer, 0, mat4Array)
    

    # 设置uniform数据的绑定组

    学习device.createBindGroup()的参数,可以类比渲染管线中.shaderLocation学习

    binding的属性值,可以设置为0、1、2、3等值进行标记。

    // 设置uniform数据的绑定组
    const bindGroup = device.createBindGroup({
        layout: pipeline.getBindGroupLayout(0),//绑定组,标记为0
        // 一个组里面可以包含多个uniform数据
        entries: [//每个元素可以用来设置一个uniform数据
            {
                binding: 0,//标记组里面的uniform数据
                resource: { buffer: mat4Buffer }
            }
        ]
    });
    

    # WGSL着色器代码声明uniform变量

    上节课缩放矩阵直接写在顶点着色器中,本节课案例,缩放矩阵写是JavaScript代码中,顶点着色器中只要在顶点着色器代码关键字@vertex之前,声明一个uniform变量表示缩放矩阵,不用赋值,注意使用<uniform>标记该变量,系统才会识别为uniform数据,这样才能通过WebGPU API把js代码中顶点数据传入顶点着色器代码中对应的uniform变量。

    var<uniform> S:mat4x4<f32>;
    @vertex
    fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> {
        // 上节课的缩放矩阵S
        // var S = mat4x4<f32>(0.5,0.0,0.0,0.0,  0.0,0.5,0.0,0.0,  0.0,0.0,1.0,0.0,  0.0,0.0,0.0,1.0);
        return S * vec4<f32>(pos,1.0);//缩放矩阵对顶点缩放变换
    }
    

    与JavaScript代码中uniform缓冲区中uniform数据关联。

    //@group(0)的参数0对应webgpu代码.getBindGroupLayout(0)参数0
    //@binding(0)的参数对应webgpu代码.binding的值,保持一致,比如都是0
    @group(0) @binding(0) var<uniform> S:mat4<f32>;
    @vertex
    fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> {
        return S * vec4<f32>(pos,1.0);//缩放矩阵对顶点缩放变换
    }
    
    const bindGroup = device.createBindGroup({
        layout: pipeline.getBindGroupLayout(0),
        entries: [
            {
                binding: 0,
                resource: { buffer: mat4Buffer }
            }
        ]
    });
    

    # .setBindGroup()传递uniform数据

    // 顶点缓冲区数据和渲染管线shaderLocation: 0表示存储位置关联起来
    renderPass.setVertexBuffer(0, vertexBuffer);
    

    .setBindGroup()传递uniform数据和.setVertexBuffer()传递顶点数据的使用方法类似。

    // 把绑定组里面的uniform数据传递给着色器中uniform变量
    // 参数1的0和.getBindGroupLayout(0)参数一致,都是0
    renderPass.setBindGroup( 0, bindGroup );
    

    # 传递一个uniform浮点数数据

    声明一个uniform变量,表示三角形顶点坐标x和y方向缩放倍数

    
    @group(0) @binding(0) var<uniform> t:f32;
    @vertex
    fn main(@location(0) pos: vec3<f32>) -> @builtin(position) vec4<f32> {
        // 创建一个缩放矩阵(沿着x、y分别缩放t倍)
        //t    0    0    0
        //0    t    0    0
        //0    0    1    0
        //0    0    0    1
        // 矩阵元素一列一列输入mat4x4<f32>()
        var S = mat4x4<f32>(t,0.0,0.0,0.0,  0.0,t,0.0,0.0,  0.0,0.0,1.0,0.0,  0.0,0.0,0.0,1.0);
        return S * vec4<f32>(pos,1.0);//缩放矩阵对顶点缩放变换
    }
    

    在JavaScript代码中创建,着色器代码中的uniform变量t对应的数据,就是一个浮点数

    // 创建uniform浮点数对应的缓冲区
    const t = 0.5;//一个浮点数,表示三角形x和y两个方向的缩放倍数
    const mat4Array = new Float32Array([t]);
    const mat4Buffer = device.createBuffer({
        size: mat4Array.byteLength,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    });
    device.queue.writeBuffer(mat4Buffer, 0, mat4Array);
    

    # 练习题:给片元着色器传递颜色数据

    // 给片元着色器传递一个颜色数据
    const colorArray = new Float32Array([0.0,1.0,0.0]);//绿色
    // 在GPU显存上创建一个uniform数据缓冲区
    const colorBuffer = device.createBuffer({
        size: colorArray.byteLength,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
    });
    // colorArray里面颜色数据写入uniform缓冲区colorBuffer
    device.queue.writeBuffer(colorBuffer, 0, colorArray);
    
    // 设置uniform数据的绑定组
    // 学习createBindGroup的参数,可以类比渲染管线中shaderLocation学习
    const bindGroup = device.createBindGroup({
        // .getBindGroupLayout(0)参数0对应shader中@group(0)代码的参数0
        layout: pipeline.getBindGroupLayout(0),//绑定组,标记为0
        // 一个组里面可以包含多个uniform数据
        entries: [//每个元素可以用来设置一个uniform数据
            {
                //binding的值对应@binding(0)的参数,保持一致,比如都是0
                binding: 0,//标记组里面的uniform数据
                resource: { buffer: mat4Buffer }
            },
            {
                //binding的值对应@binding(1)的参数,保持一致,比如都是1
                binding: 1,//标记组里面的uniform数据
                resource: { buffer: colorBuffer }
            }
        ]
    });
    
    // uniform关键字辅助var声明一个三维向量变量color表示片元颜色
    //@binding(1)的参数对应webgpu代码.binding的值,保持一致,比如都是1
    @group(0) @binding(1) var<uniform> color:vec3<f32>;
    @fragment
    fn main() -> @location(0) vec4<f32> {
        // return vec4<f32>(1.0, 0.0, 0.0, 1.0);
        return vec4<f32>(color, 1.0);
    }
    

    # 练习题:传递两个矩阵数据

    参考课件案例源码4

    4. 顶点着色器矩阵变换
    6. gl-matrix生成顶点着色器的矩阵

    ← 4. 顶点着色器矩阵变换 6. gl-matrix生成顶点着色器的矩阵→

    Theme by Vdoing | Copyright © 2016-2025 豫ICP备16004767号-2
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式