WebGPU入门一

1 WebGPU学习开发环境配置

WebGPU的环境配置比较简单,不需要vite或webpack配置一个复杂的开发环境,直接使用.html文件即可。

1.1 支持WebGPU的浏览器

Chrome 113 beta测试版开始默认支持WebGPU。

1.2 index.html文件

创建index.html文件,<script>标签设置type=“module”,就可以在模块中编写ES6语法,不需要webpack和vite进行编译处理。

1.3 vscode编辑器

借助live server插件,就可以在代码页面直接右键在live server中打开,默认浏览器中打开执行。

测试是否支持webgpu

if (navigator.gpu) {console.log("support webgpu");
} else {console.log("not support webgpu");
}

2 WebGPU API和Canvas画布

WebGPU提供了很多相关的API,通过这些WebGPU API可以控制你的显卡GPU渲染3D场景计算数据

WebGPU API文档:https://www.w3.org/TR/webgpu/

 GPU:图形处理器,即电脑上的显卡,如果为了追求更好的性能,一般会在电脑上安装独立显卡。

2.1 使用WebGPU API获取到GPU设备对象

//浏览器请求GPU适配器
const adapter = await navigator.gpu.requestAdapter();
//获取GPU设备对象,通过GPU设备对象就可以使用WebGPU API控制GPU渲染过程
const device = await adapter.requestDevice();

获取GPU设备对象非常简单,执行上面两步操作即可。

***注意***

  • requestAdapter()和requestDevice都是异步函数,函数前需要加上es6语法关键字await

 device设备对象有很多方法和属性,可以去控制物理上的显卡GPU。

 2.2 device设备对象的属性和方法

device.createRenderPipeline();//创建渲染管线
device.createComputePipeline();//创建计算管线
device.createShaderModule();//创建着色器模块
device.createCommandEncoder();//创建命令对象(绘制和计算命令)
device.createBuffer();//创建缓冲区对象

device.createCommandEncoder();//创建命令对象(绘制和计算命令),不是创建编码器。

 2.3 获取WebGPU上下文

Canvas元素作为WebGPU的画布

const canvas = document.getElementById("player");
const context = canvas.getContext("webgpu");

2.4 配置WebGPU上下文

关联Canvas对象和GPU设备对象device。这样就能把Canvas元素作为WebGPU的画布,用来呈现3D渲染效果。

//配置webgpu上下文(canvas上下文和device绑定在一起):device设备,format颜色格式,
const format = navigator.gpu.getPreferredCanvasFormat();//获取浏览器canvas默认的颜色格式
context.configure({device:device,format:format,
})

3 创建顶点缓冲区、渲染管线

如果想渲染一个物体,需要先通过顶点坐标来定义该物体的几何形状。通过WebGPU的顶点缓冲区来创建顶点数据。

3.1 WebGPU坐标系

坐标原点是Canvas画布的中间位置,x轴水平向右,y轴竖直向上,Z轴与canvas画布垂直,朝向屏幕内。x,y取值范围【-1,1】,z取值范围【0,1】。(归一化)

用x,y分量可绘制2D平面图。3D效果会用到z坐标投影矩阵视图矩阵模型矩阵等深入概念。

3.2 类型化数组Float32Array表示顶点坐标

3.2.1 JavaScript类型化数组

JavaScript类型化数组不同于普通的数组,类型化数组就是数组的元素可以设置数字的类型,比如浮点数、无符号整数..

3.2.2 类型化数组Float32Array表示顶点坐标

 const vertexArray = new Float32Array([//三角形三个顶点坐标的x,y,z值0.0,0.0,0.0,//顶点1坐标1.0,0.0,0.0,//顶点2坐标0.0,1.0,0.0,//顶点3坐标
]);

3.2.3 创建顶点缓冲区.createBuffer

通过GPU设备对象的.createBuffer()方法可以创建一个顶点缓冲区。当device.createBuffer执行的时候,会在你的电脑显卡GPU的内存(显存)中开辟一片存储空间,用来存储顶点数据,你可以把这个开辟的存储空间,称为顶点缓冲区

const vertexBuffer = device.createBuffer();

3.2.4 缓冲区设置

const vertexBuffer = device.createBuffer({size:vertexArray.byteLength,//长度:数据字节usage:GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,//用途:作为顶点缓冲区|可以写入顶点数据
});

 3.2.5 顶点数据写入顶点缓冲区

把类型化数组中的数据写入创建的顶点缓冲区:GPU设备对象device队列属性.queue的方法.writeBuffer()。参数2表示从vertexArray获取顶点数据的偏移量(单位字节),0表示从vertexArray的数据开头读取数据。

device.queue.wirteBuffer(vertexBuffer,0,vertexArray);//把vertexArray里面的顶点数据写入到vertexBuffer对应的GPU显存缓冲区中。

3.2.6 创建渲染管线和设置参数

通过GPU设备对象的方法.createRenderPipeline创建一个WebGPU渲染管线。

可以理解为工厂中的流水线,通过流水线处理顶点缓冲区中的数据。

const pipeline = device.createRenderPipeline({vertex:{buffers:[{arrayStride:3*4,//一个顶点数据占用的字节长度attributes:[{//顶点缓冲区属性shaderLocation:0,//GPU显存上顶点缓冲区标记存储位置format:"float32x3",//格式:3个float32offset:0//arrayStride每组顶点数据间隔字节数}]}]}
});

4 着色器语言WGSL

WGSL语言是专门给WebGPU定制的着色器语言,就像WebGL OpenGL中使用的GLSL着色器语言。

WGSL英文文档:WebGPU Shading Language

WebGPU引擎Orillusion团队翻译:WebGPU Shading Language

WebGPU Shading Language

 TypeScript、C语言等都在CPU执行,而WGSL主要在GPU上执行,有自身的特殊性。

4.1 WGSL基础类型

符号数据类型
bool布尔
u32无符号整数
i32有符号整数
f3232位浮点数
f1616位浮点数

 4.2 关键字声明变量

 WGSL中使用var关键字声明变量。

//var关键字声明一个变量a,数据类型是无符号整数
var a:u32;
u32 = 2;//数据类型是32位浮点数
var a:f32;
a = 2.0;//声明时直接赋值
var a:f32 = 3.0;

 如果不加u32或f32,WGSL会根据值进行自动推断。

4.3 变量简单运算

两个变量进行运算,需要保持一样的数据类型,否则报错。

//32位浮点数相加
var a:f32 = 2.0;
var b:f32 = 4.0;
var c:f32 = a + b;//无符号整数相加
var a:u32 = 2;
var b:u32 = 4;
var c:u32 = a + b;

4.4 声明函数的关键字

fn 函数名(参数1:数据类型,参数2:数据类型...){//代码
}//例如:
fn add(x:f32,y:f32){var z:f32 = x + y;
}

如果函数有返回值,设置符号->,后面注明返回值的数据类型

fn 函数名(参数1,参数2)-> 返回值数据类型{return 返回值;
}
//例如:fn add(x:f32,y:f32)->f32{return x + y;
}

4.5 if、for等语句

在WGSL中,if、for等语句,和JavaScript逻辑上差不多,区别就是注意数据类型即可。

var n:u32 = 10;
var s:f32 = 0.0;for(var i:u32 = 0;i<n;i++){s += 0.5;
}

 4.6 向量表示颜色

四维向量有4个分量,可以用来表示颜色的R、G、B、A。

var color:vec4<f32> = vec4<f32>(1.0,0.0,0.0,1.0);//红色不透明//省略:vec4<f32>数据类型=>系统自动识别
var color = vec4<f32>(1.0,0.0,0.0,1.0);//先声明一个四维向量变量,再赋值,此时声明必须带着类型
var color:vec4<f32>;
color = vec4<f32>(1.0,0.0,0.0,1.0);

 4.7 向量表示位置

三维向量vec3<f32>表示具有三个分量,可以用来表示顶点的xyz坐标。

var pos:vec3<f32>;
pos = vec3<f32>(1.0,2.0,3.0);

xyz的齐次坐标:前三个变量为x,y,z,最后一个分量是1.0

var pos:vec4<f32>;
pos = vec4<f32>(1.0,2.0,3.0,1.0);

一个三维向量转化为四维向量

var pos:vec3<f32>;
pos = vec3<f32>(1.0,2.0,3.0);
//转换为四维向量
var pos2 = vec4<f32>(pos,1.0);

一个二维向量转换为四维向量

var pos:vec2<f32>;
pos = vec2<f32>(1.0,2.0);
//转换为四维向量
var pos2 = vec4<f32>(pos,3.0,1.0);

4.8 结构体

struct pointLight {color:vec3<f32>,//光源颜色intensity:f32//光源强度
}

通过结构体生成一个光源,类似JavaScript中类执行new 实例化一个对象。

var linght1:pointLight;
light1.color = vec3<f32>(1.0,0.0,0.0);
light1.intensity = 0.6;

 4.9 WGSL语句结尾分号

在JavaScript中,代码语句结尾的分号可以省略,但是WGSL中分号不能省略。

5 顶点着色器

你把渲染管线想象成为工厂的一条流水线,顶点着色器想象为流水线上的一个工位。

GPU渲染管线上提供的顶点着色器单元的功能就是计算顶点,即对顶点坐标x,y,z的值进行平移、旋转、缩放等各种操作。

5.1 顶点着色器代码

GPU渲染管线上的顶点着色器功能单元,可以执行WGSL着色器语言编写的代码。所有顶点数据经过顶点着色器时,都会执行顶点着色器代码中顶点计算的函数,比如平移顶点坐标。

5.2 WGSL着色器代码形式

在JavaScript或TypeScript写WebGPU代码时,按照语法要求,WGSL着色器的代码,要以字符串的形式存在。

如果直接在单引号或双引号表示的字符串里面写WGSL代码,实现字符串的多行书写,需要用+号连接,不是很方便。

使用ES6的语法模板字符串 ` `(反引号),实现字符串的多行书写很方便。

5.3 @vertex 

@vertex表示字符串vertex里面的代码是顶点着色器代码,在GPU渲染管线的顶点着色器单元上执行。

const vertexShaderSource = `@vertex
`

5.4 fn关键字声明一个函数

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

@vertex
fn main(){}

5.5 location 关键字

location是WGSL语言的一个关键字,通常用来指定顶点缓冲区相关的顶点数据,使用location的时候需要加上@符号前缀,@location()小括号里面设置参数。

main函数的参数@location(0)表示GPU显存中标记为0(参数和创建渲染管线中的shaderLocation的参数一一对应)的顶点缓冲区中顶点数据。

@vertex
fn main(@location(0)){}

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

@vertex
fn main(@location(0) pos){}

pos变量:通过location(0)拿到顶点缓冲区中的数据。

5.6 顶点变量的数据类型

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

@vertex
fn main(@location(0) pos:vec3<f32>){}

注意location(0)对应的WebGPU传过来的顶点是三个为一组(顶点缓冲区、渲染管线中的format设置),顶点着色器代码中的pos变量的数据类型用三维向量表示。如果WebGPU传过来的顶点数据两个为一组,书写形式为@location(0) pos:vec2<f32>

5.7 vec3顶点坐标转vec4齐次坐标

在WGSL顶点着色器代码中,很多时候会用四维向量vec4表示顶点的位置坐标,vec4第四个分量默认值一般是1.0,vec4比vec3多了一个分量,把vec4形式的坐标称为齐次坐标

@vertex
fn main(@location(0) pos:vec3<f32>){var pos2 = vec4<f32>(pos,1.0);//pos转齐次坐标
}

5.8 顶点计算后,return返回顶点数据

实际开发,一般会在main函数中,进行顶点坐标的几何变换,例如:平移、缩放、旋转等。几何变换后,需要return返回,供下一个功能单元使用

@vertex
fn main(@location(0) pos:vec3<f32>)->vec4<f32>{var pos2 = vec4<f32>(pos,1.0);pos2.x -=0.2;//偏移所有顶点的x坐标return pos2;
}

5.9 内置变量position和@builtin关键字

内置变量:WGSL默认提供的变量,不需要通过关键字var声明就可以使用。

position是WGSL语言的一个内置变量,表示顶点数据。main函数的返回是顶点数据,这时候除了要设置返回值类型,还需要设置@builtin(position)表明返回值是顶点位置数据。

@vertex
fn main(@location(0) pos:vec3<f32>)->@builtin(position) vec4<f32>{var pos2 = vec4<f32>(pos,1.0);pos2.x -=0.2;//偏移所有顶点的x坐标return pos2;
}

5.10 着色器代码块方法.createShaderModule()和指定入口函数

device.createShaderModule();

指定顶点着色器代码的入口函数,入口函数名称可以自定义。

//创建一个WebGPU渲染管线对象pipeline
const pipeline = device.createRenderPipeline({vertex:{module:device.createShaderModule({code:vertex}),entryPoint: "main",buffers:[{arrayStride:3*4,//一个顶点数据占用的字节长度attributes:[{//顶点缓冲区属性shaderLocation:0,//GPU显存上顶点缓冲区标记存储位置format:"float32x3",//格式:3个float32offset:0//arrayStride每组顶点数据间隔字节数}]}]}
});

6 图元装配和光栅化

渲染管线上的其他功能单元(图元装配、光栅化、片元着色器)。

6.1 图元装配

经过顶点着色器处理过的顶点数据,会进入图元装配环节,简单说就是如何通过顶点数据生成几何图形,例如三个点绘制一个三角形,两点可以绘制一条线段等。

通过渲染管线参数的primitive.topology属性可以设置WebGPU如何绘制顶点数据。

const pipeline = device.createRenderPipeline({vertex:{module:device.createShaderModule({code:vertex}),entryPoint: "main",buffers:[{arrayStride:3*4,//一个顶点数据占用的字节长度attributes:[{//顶点缓冲区属性shaderLocation:0,//GPU显存上顶点缓冲区标记存储位置format:"float32x3",//格式:3个float32offset:0//arrayStride每组顶点数据间隔字节数}]}]},primitive:{topology: "triangle-list",//绘制三角形、线line-strip(多个点连接成线)、point-list}});

6.2 光栅化(没有代码)

光栅化:生成几何图形对应的片元,你可以把片元类比为图像上一个个像素,例如绘制一个三角形,相当于在三角形内部,生成一个一个密集排列的片元(像素)。

经过光栅化的片元,是没有任何颜色的片元(像素),需要通过渲染管线上的片元着色器上色,片元着色器单元就像流水线上一个喷漆的工位一样,给物体设置外观颜色。 

7 片元着色器

一个个片元就像一个个顶点一样。

片元着色器和顶点着色器类似,都是渲染管线上的一个着色器功能单元,可以执行WGSL着色器代码。

7.1 @fragment关键字

表示后续代码为片元着色器代码。

7.2 返回值和类型

片元着色器中的@location(0)和前面顶点着色器中的@location(0)虽然符号一样,但含义不同。

片元着色器中的@location(0)和顶点数据没关系。渲染管线片元着色器输出的片元像素数据,会存储在显卡内存上,@location(0)表示输出的片元数据存储到显卡内存上,并把存储位置标记为0,用于渲染管线的后续操作和处理。

const fragmentShaderSource = `@framentfn main() ->location(0) vec4<f32>{return vec4<f32>(1.0,0.0,0.0,1.0);//片元设置为红色	}
`

7.3 渲染管线设置fragment属性

module模块、entryPoint入口函数、targets的format格式。

const pipeline = device.createRenderPipeline({vertex:{module:device.createShaderModule({code:vertexShaderSource}),entryPoint: "main",buffers:[{arrayStride:3*4,//一个顶点数据占用的字节长度attributes:[{//顶点缓冲区属性shaderLocation:0,//GPU显存上顶点缓冲区标记存储位置format:"float32x3",//格式:3个float32offset:0//arrayStride每组顶点数据间隔字节数}]}]},fragment:{module:device.createShaderModule({code:fragmentShaderSource}),entryPoint: "main",targets: [{ format: format }]}primitive:{topology: "triangle-list",//绘制三角形、线line-strip(多个点连接成线)、point-list}});

学习WebGPU主要是控制渲染管线。

8 渲染命令

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

通过GPU设备对象的方法.createCommandEncoder()创建一个命令编码器对象。创建一个渲染通道对象renderPass,他可以控制渲染管线pipeline渲染输出像素数据。

canvas画布有一个默认的颜色缓冲区,可以直接使用,当然你也可以自己创建一个颜色缓冲区。

颜色缓冲区:通过WebGPU渲染管线各个功能处理后,会得到图形的片元数据、或像素数据,这些像素数据,会存储到显卡内存颜色缓冲区中。顶点缓冲区的功能是存储顶点数据,颜色缓冲区的功能是存储渲染管线输出的像素数据。

//创建GPU命令编码器对象
const commanEncoder = device.createCommandEncoder();

8.2 .beginRenderPass的参数对象

renderPass有很多属性对象。常用的有colorAttachments(颜色附件),

//创建一个渲染通道对象renderPass
const renderPass = commandEncoder.beginRenderPass({colorAttachments: [{view: context.getCurrentTexture().createView(),//指向用于Canvas画布的纹理视图对象(Canvas对应的颜色缓冲区)clearValue: [1.0, 0.0, 0.0, 1.0],//背景颜色loadOp: "clear",storeOp: "store",//像素数据写入颜色缓冲区},],
});

8.3 设置渲染通道的渲染管线

//设置渲染管线
renderPass.setPipeline(pipeline);

8.4 关联顶点缓冲区和渲染管线

将顶点缓冲区和createRenderPipeline中的shaderLocation创建联系。

renderPass.setVertexBuffer(0,vertexBuffer);

总结:

在渲染管线中配置顶点着色器的属性时,会设置shaderLocation:0,这表示GPU中0位置的数据;在顶点着色器中会使用@location(0)进行访问。

而顶点缓冲区并没有映射到GPU的0位置,因此需要setVertexBuffer进行设置。

8.5 绘制命令和结束命令

1、把渲染管线中的内容绘制到canvas上。

2、结束命令编码器的渲染通道对象

renderPass.draw(3);//绘制三个点
renderPass.end();//结束命令编码器的渲染通道对象

前面代码调用的WebGPU API,大部分都是用来控制GPU如何运行的,例如:device.createRenderPipeline()控制GPU创建一个渲染管线;.draw方法控制GPU如何绘制顶点数据,不过这些WebGPU API不能直接控制GPU的运行,需要转化为GPU指令,才能控制GPU运转。

8.6 命令编码器方法.finish()

命令编码器对象commandEncoder执行.finish()方法返回一个命令缓冲区对象,同时会把该编码器相关的WebGPU api编码为GPU指令,存入到返回的命令缓冲区对象中。

8.7 GPU设备命令队列.queue属性

GPU设备命令队列.queue的功能是用来存放控制GPU运转的指令(命令),简单说就是你命令编码器和渲染通道定义的一系列控制GPU运行的命令方法。

.submit()是GPU设备对象device队列属性.queue的一个提交方法。

提交方法.submit()的参数是一个数组,数组的元素是命令编码器执行.finish()生成的GPU命令缓冲区对象commandBuffer,数组元素可以包含多个命令缓冲区对象。

device.queue.submit([commandEncoder.finish()]);

待做:

vscode中WGSL插件

在/*wgsl*/` `;反引号中的内容会变成彩色。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/161250.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++进阶篇1---继承

一、继承的概念和定义 1.1概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称为派生类。继承呈现了面向对象程序设计的层次结构&#xff…

ExoPlayer架构详解与源码分析(5)——MediaSource

系列文章目录 ExoPlayer架构详解与源码分析&#xff08;1&#xff09;——前言 ExoPlayer架构详解与源码分析&#xff08;2&#xff09;——Player ExoPlayer架构详解与源码分析&#xff08;3&#xff09;——Timeline ExoPlayer架构详解与源码分析&#xff08;4&#xff09;—…

掌握Python爬虫实现网站关键词扩展提升曝光率

目录 一、关键词优化的重要性 二、关键词优化的基本方法 1、选择与网站内容相关的关键词 2、控制关键词的密度和分布 3、关键词的层次布局 三、Python爬虫实现网站关键词扩展 1、确定目标网站 2、分析目标网站的HTML结构 3、编写Python爬虫代码 4、分析爬取到的关键词…

【算法练习Day22】 组合总和 III电话号码的字母组合

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 组合总和 III剪枝 电话号码…

深入理解React中的useEffect钩子函数

引言&#xff1a; React是一种流行的JavaScript库&#xff0c;它通过组件化和声明式编程的方式简化了前端开发。在React中&#xff0c;一个核心概念是组件的生命周期&#xff0c;其中包含了许多钩子函数&#xff0c;用于管理组件的不同阶段。其中之一就是useEffect钩子函数&…

LuaJit交叉编译移植到ARM Linux

简述 Lua与LuaJit的主要区别在于LuaJIT是基于JIT&#xff08;Just-In-Time&#xff09;技术开发的&#xff0c;可以实现动态编译和执行代码&#xff0c;从而提高了程序的运行效率。而Lua是基于解释器技术开发的&#xff0c;不能像LuaJIT那样进行代码的即时编译和执行。因此&…

系统架构与Tomcat的安装和配置

2023.10.16 今天是学习javaweb的第一天&#xff0c;主要学习了系统架构的相关知识和原理&#xff0c;下载了web服务器软件&#xff1a;Tomcat&#xff0c;并对其进行了配置。 系统架构 包括&#xff1a;C/S架构 和 B/S架构。 C/S架构&#xff1a; Client / Server&#xff0…

离散数学 学习 之 递推方程和生成函数

递推方程 注意这里的特征根一定不是相等 特解的话一般要去设出基本的形式 这是0 次多项式 生成函数

【JAVA】集合与背后的逻辑框架,包装类,List,Map,Set,静态内部类

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 collectionCollection创建collection使用泛型collection方法 Map 接口Map的存储结构HashMap和Tr…

lenovo联想笔记本ThinkPad系列T15p或P15v Gen3(21DA,21DB,21D8,21D9)原厂Win11系统镜像

下载链接&#xff1a;https://pan.baidu.com/s/1V4UXFhYZUNy2ZQ8u4x1AFg?pwdqz0s 系统自带指纹驱动、人脸识别驱动、显卡、声卡等所有驱动、出厂主题壁纸、Office办公软件、Lenovo联想电脑管家等预装程序 所需要工具&#xff1a;32G或以上的U盘 文件格式&#xff1a;ISO …

一篇文章带你搞定所有二叉树题型的递归思维(思路超详细)

文章目录 &#x1f380;前言&#xff1a;&#x1f3c5;先在开头总结一下&#xff0c;二叉树解题的思维模式分两类&#xff1a;&#x1f387;先解释一下“前序位置”&#xff0c;“后序位置”的意思&#x1f3e8;举一个简单的例子&#xff1a; &#x1fa80;下面通过两道例题&am…

从自动化到测开,测试人员逆袭之路从此起步

在当今竞争激烈的软件测试行业中&#xff0c;近期的招聘市场确实面临一些挑战。大量的求职者争相涌入岗位&#xff0c;许多热衷于功能测试的人士甚至难以找到理想的工作机会。更不幸的是&#xff0c;连自动化测试和性能测试这些专业领域也受到了测试开发人员的竞争压力。然而&a…

C# 图解教程 第5版 —— 第4章 类型、存储和变量

文章目录 4.1 C# 程序是一组类型声明4.2 类型是一种模板&#xff08;*&#xff09;4.3 实例化类型4.4 数据成员和函数成员4.5 预定义类型4.6 用户定义类型4.7 堆和栈&#xff08;*&#xff09;4.8 值类型和引用类型4.9 变量4.9.1 变量声明4.9.2 多变量声明&#xff08;*&#x…

模式植物背景基因集制作

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 写在前面 关于GO背景基因集文件的制作&#xff0c;我们在很早以前也发过。近两天&#xff0c;自己在分析时候&#xff0c;也是被搞了头疼。想重新制作一份GO背景基因集&#xff0c;进行富集分析。但是结果&…

排序【七大排序】

文章目录 1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2. 常见排序算法的实现2.1 插入排序2.1.1基本思想&#xff1a;2.1.2 直接插入排序2.1.3 希尔排序( 缩小增量排序 ) 2.2 选择排序2.2.1基本思想&#xff1a;2.2.2 直接选择排序:2.2.3 堆排序 2.3 交换排序2.3.1冒…

uniapp小程序中给web-view页面添加授权弹窗(使用cover-view组件覆盖实现该功能)

效果图&#xff1a; web-view是承载网页的容器。会自动铺满整个小程序页面&#xff0c;个人类型的小程序暂不支持使用。 再看下面一个提示&#xff1a; 每个页面只能有一个 web-view&#xff0c;web-view 会自动铺满整个页面&#xff0c;并覆盖其他组件。 也就是说&#xff0c;…

云安全—云计算基础

0x00 前言 学习云安全&#xff0c;那么必然要对云计算相关的内容进行学习和了解&#xff0c;所以云安全会分为两个部分来进行&#xff0c;首先是云计算先关的内容。 0x01 云计算 广泛传播 云计算最早大范围传播是2006年&#xff0c;8月&#xff0c;在圣何塞【1】举办的SES&a…

七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)

一&#xff1a;排序的概念及引入 1.1 排序的概念 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在…

DITA-OT 4.0新特性 - PDF themes,定制PDF样式的新方法

随着DITA-OT 4.0的发布&#xff0c;它提供了一种新的定制PDF样式方法&#xff0c;这种方法就是PDF theme。这篇文章来聊一聊这种定制PDF输出的新方法和实验结果。 在进入PDF theme细节之前&#xff0c;为各位读者梳理一下DITA-OT将DITA和Markdown发布成PDF的几种方法。 - 1 …

element ui 下拉框 选择月份和天数

一、背景 目前做的管理系统项目&#xff0c;期望实现功能为&#xff1a;设置出账周期和出账日&#xff0c;考虑使用element ui下拉框实现功能 二、所用技术 vue2element ui 三、实现效果 四、具体代码 <template><popup-frame :title"批量设置出账日" …