WebGPU入门一

news2025/7/14 9:51:42

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个float32
				offset: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个float32
			offset: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个float32
				offset: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 = `
    @frament
	fn 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个float32
				offset: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.coloradmin.cn/o/1103096.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uni-app:对数组对象进行以具体某一项的分类处理

一、原始数据 这里定义为五个数组&#xff0c;种类product有aaa,bbb两种 原始数据在data中进行定义 res: {"success": true,"devices": [{no: 0,product: aaa,alias: "设备1",assign: [["a1", "a2", "a3"],[&q…

论文解析-moETM

论文解析-moETM 参考亮点动机发展现状现存问题 功能方法Encoder改进Decoder改进 评价指标生物保守性批次效应移除 实验设置结果多组学数据整合cell-topic mixture可解释性组学翻译性能评估RNA转录本、表面蛋白、染色质可及域调控关系研究1. 验证同一主题下&#xff0c;top gene…

Python武器库开发-基础篇(二)

基础篇(二) if 语句 编程时经常需要检查一系列条件&#xff0c;并据此决定采取什么措施。在Python中&#xff0c;if 语句让你能够检查程序的当前状态&#xff0c;并据此采取相应的措施 下面是一个简短的示例&#xff0c;演示了如何使用if 语句来正确地处理特殊情形。假设你有…

cmd进程简单操作指令

dir 查询当前路径和子路径 start空格加自己的exe程序&#xff0c;可运行程序。 taskkill /?可以执行很多&#xff0c;通常用于结束程序。 taskkill /f /im qq.exe 启动nginx.exe 查看运行的进程有哪些 选择结束nginx.exe

手写一个PrattParser基本运算解析器3: 基于Swift的PrattParser的项目概述

点击查看 基于Swift的PrattParser项目 PrattParser项目概述 前段时间一直想着手恶补 编译原理 的相关知识, 一开始打算直接读大学的 编译原理, 虽然内容丰富, 但是着实抽象难懂. 无意间看到B站的熊爷关于普拉特解析器相关内容, 感觉是一个非常好的切入点.所以就写了基于Swift版…

试着写几个opencv的程序

一、认识opencv OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源计算机视觉库&#xff0c;旨在提供丰富的图像处理和计算机视觉功能&#xff0c;以帮助开发者构建视觉应用程序。OpenCV最初由英特尔开发&#xff0c;现在由社区维护和支持。它支持…

【Javascript保姆级教程】显示类型转换和隐式类型转换

文章目录 前言一、显式类型转换1.1 字符串转换1.2 数字转换1.3 布尔值转换 二、隐式类型转换2.1 数字与字符串相加2.2 布尔值与数字相乘 总结 前言 JavaScript是一种灵活的动态类型语言&#xff0c;这意味着变量的数据类型可以在运行时自动转换&#xff0c;或者通过显式类型转…

Vue3使用Vite创建项目

node版本&#xff1a;node -v v18.16.0 npm版本: npm -v 9.5.1 Vite Vite&#xff1a;是一种新型前端构建工具&#xff0c;能够显著提升前端开发体验 脚手架&#xff0c;创建Vue项目&#xff0c;替代 Vue-cli 基于Vite创建vue项目&#xff1a; 1.npm create vitelatest 2.完…

只要封装相同,电容体本身大小就一样吗?

高速先生成员--黄刚 当然这篇文章也还是针对高速信号的交流耦合电容&#xff0c;并不是用于电源的去耦电容&#xff0c;同时文章的灵感也来源于上一篇文章讲不同容值电容对高速信号原理上的效果差异。为什么我们在做高速设计的时候&#xff0c;速率越高&#xff0c;希望电容封装…

硬件小白,如何在有限的预算里选择一款性价比最高的硬盘?

硬件小白&#xff0c;如何在有限的预算里选择一款性价比较高的硬盘 明确使用场景三大种类SSD、HHD、HDDSSD 固态硬盘&#xff08;Solid State Drive&#xff09;HHD 混合硬盘&#xff08;Hybrid Hard Drive)HDD 传统硬盘&#xff08;Hard Disk Drive&#xff09;小结 重要参数机…

3分钟了解 egg.js

Eggjs是什么&#xff1f; Eggjs是一个基于Koajs的框架&#xff0c;所以它应当属于框架之上的框架&#xff0c;它继承了Koajs的高性能优点&#xff0c;同时又加入了一些约束与开发规范&#xff0c;来规避Koajs框架本身的开发自由度太高的问题。 Koajs是一个nodejs中比较基层的…

MFC-列表控件

目录 1、更改列表控件的属性&#xff1a; 2、代码设置表头&#xff1a; 3、设置正文内容&#xff1a; 4、设置属性&#xff0c;显示成表格形式 &#xff1a; 5、代码实现&#xff1a; 1、更改列表控件的属性&#xff1a; VIEW设置为Report模式会出现表格形状 2、代码设置…

C++对象模型(14)-- 构造函数语义学:拷贝构造函数和赋值运算赋

1、拷贝构造函数 1.1 什么是拷贝构造函数 拷贝构造函数是一种构造函数&#xff0c;它的功能是创建新对象。也就是说对象还没生成&#xff0c;这时利用另一个对象的拷贝来生成新的对象。 class MyDemo { public:// 默认构造函数MyDemo(){}// 拷贝构造函数MyDemo(const MyDemo…

【Java 进阶篇】JavaScript DOM Document对象详解

在前端开发中&#xff0c;DOM&#xff08;文档对象模型&#xff09;扮演着重要的角色。它允许我们使用JavaScript来与网页文档进行交互&#xff0c;实现动态的网页效果。DOM的核心部分之一就是Document对象&#xff0c;它代表了整个HTML文档。在本篇博客中&#xff0c;我们将深…

A1S65B-S1 A1S61PN A1SJ51T64 机器人的优点和缺点

A1S65B-S1 A1S61PN A1SJ51T64 机器人的优点和缺点 像今天的任何创新一样&#xff0c;机器人有其优缺点。以下是机器人的优缺点和机器人未来的分析。 优势 他们在危险的环境中工作:当你可以派一个机器人去做这项工作时&#xff0c;为什么要拿人命冒险呢&#xff1f;想想看&a…

电平转换器IC

一、前言 使用多款电平转换器&#xff0c;记录和分享使用心得 目录 1.TXB0104(非国产) 2.RS0104(国产) 二、环境 非隔离电平转换&#xff0c;1.8~5V 三、正文 1.TXB0104(非国产) 芯片简介&#xff1a;A 端口支持 1.2V 至 3.6V 的电压&#xff0c;B 端口支持 1.65V 至 5…

法国数字医疗公司Tilak Healthcare完成1000万欧元融资

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;总部位于法国巴黎的治疗眼科的数字医疗公司Tilak Healthcare今日宣布已完成1000万欧元融资。 本轮融资完成后&#xff0c;Tilak Healthcare的融资总额已达到2200万欧元&#xff0c;本轮融资由Elai…

【软件测试】高频常问自动化测试面试题+答案(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、你有没有做过自…

linux文件权限与目录配置

用户与用户组 linux一般将文件可读写的身份分为三个类别&#xff1a;拥有者&#xff08;owner&#xff09;、所属群组&#xff08;group&#xff09;、其他人&#xff08;other&#xff09; 三种身份都有读、写、执行等权限 文件拥有者 linux是个多人多任务的系统&#xff0c…

Edge侧实用【AI插件合集】

废话不多说&#xff0c;直接开始正文&#x1f447; 1.ChatsNow ChatsNow是人工智能助手&#xff0c;支持GPT-3.5 和 GPT-4 模型&#xff0c;写作&#xff0c;AI绘画统统不在话下&#xff0c;并且可以增强搜索引擎结果等。 免费使用&#xff0c;提供30次问答次数&#xff0c;…