前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

WebGL

原创
作者头像
粗来丸
发布2024-08-23 15:45:18
590
发布2024-08-23 15:45:18

顶点着色器

顶点着色器代码
顶点着色器代码

按照语法要求,WGSL着色器的代码,要以字符串的形式存在。若使用ES6的语法模板字符串``(反引号),实现字符串的多行书写很方便。

@vertex,说明此处是WGSL语言;

fn 关键字声明一个函数,命名为main,作为顶点着色器代码的入口函数。fn 关键字类似JavaScript语言的 function 关键字,用来声明一个函数;

@location( ),用来指定顶点缓冲区相关的顶点数据 、@location(0)表示GPU显存中标记为0的顶点缓冲区中顶点数据。

执行@location(0) pos给main函数参数@location(0)表示的顶点数据设置一个变量名pos。

执行@location(0) pos: vec3<f32>给main函数参数pos设置数据类型;vec3表示pos变量的数据类型是三维向量,<f32>表示三维向量x、y、z几个属性的值都是32位浮点数。

在WGSL中,数据类型除了三维向量vec3,还有四维向量vec4,从三维是可以转换到四维向量的:

渲染管线是一条流水线,顶点着色器处理好的顶点数据,最后需要通过关键字return返回,这样渲染管线的下个环节,就可以使用了

顶点着色器的工作结束,return pos2
顶点着色器的工作结束,return pos2

main函数return返回的变量,需要通过->符号设置函数返回值的数类类型,-> vec4<f32>表示函数返回的变量是浮点数构成的四维向量vec4

main函数的返回是顶点数据,这时候除了设置返回值数据类型,还需要设置@builtin(position),表明返回值是顶点位置数据。

将顶点着色器代码转换为GPU着色器代码块

通过GPU设备对象的 .createShaderModule() 方法

代码语言:txt
复制
// 引入顶点着色器vertex代码对应字符串
import { vertex } from './shader.js'
// 字符串形式的顶点着色器代码作为code属性的值
device.createShaderModule({ code: vertex })

把顶点着色器代码块对象device.createShaderModule({ code: vertex })作为渲染管线参数vertex.module属性的值,这样就可以配置好渲染管线上顶点着色器功能单元,要执行的顶点着色器代码。

代码语言:txt
复制
const pipeline = device.createRenderPipeline({
    vertex: {
        // 设置渲染管线要执行的顶点着色器代码
        module: device.createShaderModule({ code: vertex }),
        entryPoint: "main"
    },
});
  • entryPoint 属性指定着色器代码的入口函数;

图元装配: primitive.topology

代码语言:txt
复制
const pipeline = device.createRenderPipeline({
    primitive: {
        topology: "triangle-list",// 绘制三角形
        //topology: "line-strip",// 多个定点依次连线
        //topology: "point-list",// 每个顶点坐标对应位置渲染一个小点
    }
});

光栅化、片元着色器

经过光栅化处理得到的片元,你可以认为是一个没有任何颜色的片元(像素),需要通过渲染管线上片元着色器上色,片元着色器单元就像流水线上一个喷漆的工位一样,给物体设置外观颜色。片元着色器同顶点着色器一样,只能识别WGSL语言

代码语言:txt
复制
@fragment
fn main() -> @location(0) vec4<f32> {
    return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
  1. @location(0),输出的片元像素数据存储到显卡内存上,并把位置标注为0,用于渲染管线的后续操作和处理。
  2. 片元着色器中的 @location(0) 和顶点缓冲区中顶点数据也没关系。
代码语言:javascript
复制
import { vertex, fragment } from './shader.js'
const pipeline = device.createRenderPipeline({
    layout: 'auto',
    vertex: {
        module: device.createShaderModule({ code: vertex }),
        entryPoint: "main"//指定入口函数
    },
    fragment: {
        // module:设置渲染管线要执行的片元着色器代码
        module: device.createShaderModule({ code: fragment }),
        entryPoint: "main",//指定入口函数,
        targets: [{
            format: format//和WebGPU上下文配置的颜色格式保持一致
        }]
    }
});

创建命令编码器commandEncoder和渲染通道renderPass

  1. 首先通过GPU设备对象的方法.createCommandEncoder()创建一个命令编码器对象。
代码语言:javascript
复制
const commandEncoder = device.createCommandEncoder();

2. 通过命令对象的方法.beginRenderPass()可以创建一个渲染通道对象 renderPass

代码语言:javascript
复制
const renderPass = commandEncoder.beginRenderPass({
    // 需要配置一些参数
});

3. 通过GPU命令编码器对象commandEncoder可以控制渲染管线pipeline渲染输出像素数据。

颜色缓冲区的概念

类比顶点缓冲区和理解颜色缓冲区,顶点缓冲区的功能是存储顶点数据,颜色缓冲区的功能是存储渲染管线输出的像素数据。颜色缓冲区和顶点缓冲区类似,可以创建,不过有一个比较特殊,就是canvas画布对应一个默认的颜色缓冲区,可以直接使用。如果你希望webgpu绘制的图形,呈现在canvas画布上,就要把绘制的结果输出到canvas画布对应的颜色缓冲区中

.beginRenderPass()创建的 渲染通道 对象 renderPass 具有多个属性,比如:colorAttachments(颜色附件) 渲染通道 renderpass 可以控制渲染管线 pipeline 的渲染像素数据,输出的像素数据会储存到颜色缓冲区;

colorAttachments属性就和颜色缓冲区有关,colorAttachments属性的值是数组,数组里面的元素是对象,可以包含多个对象,每个对象的都和一个颜色缓冲区相关,每个对象具有viewloadOpstoreOpclearValue等属性。当需要把渲染管线的像素数据要储存到多个缓冲区时,数组中才需要设置多个对象;

代码语言:javascript
复制
const renderPass = commandEncoder.beginRenderPass({
    // 给渲染通道指定颜色缓冲区,配置指定的缓冲区
    colorAttachments:[{
        // 指向用于Canvas画布的纹理视图对象(Canvas对应的颜色缓冲区)
        // 该渲染通道renderPass输出的像素数据会存储到Canvas画布对应的颜色缓冲区(纹理视图对象)
        view: context.getCurrentTexture().createView(),  
        storeOp: 'store',//像素数据写入颜色缓冲区
        loadOp: 'clear',
        clearValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 }, //背景颜色
    }]
});

顶点缓冲区数据0与渲染管线shaderLocation相关联

代码语言:javascript
复制
renderPass.setPipeline(pipeline);

  • 实际开发,可以通过device.createBuffer()创建多个顶点缓冲区,第一个案例,只有一个顶点缓冲区 .setVertexBuffer() 的参数1设置为0即可

绘制命令

渲染通道对象renderPass提供了一个方法.draw()

代码语言:javascript
复制
// 绘制命令.draw()绘制顶点数据
renderPass.draw(3);

在调用 .draw() 方法之前,要先设置渲染管线

渲染通道结束命令

渲染通道对象renderPass.end()方法比较简单,就是字面意思结束,不用设置参数。一般你设置好绘制等命令后,需要设置renderPass.end()

代码语言:javascript
复制
// 渲染通道结束命令.end()
renderPass.end();

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 顶点着色器
  • 将顶点着色器代码转换为GPU着色器代码块
  • 图元装配: primitive.topology
  • 光栅化、片元着色器
  • 创建命令编码器commandEncoder和渲染通道renderPass
  • 颜色缓冲区的概念
  • 顶点缓冲区数据0与渲染管线shaderLocation相关联
  • 绘制命令
  • 渲染通道结束命令
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档