【技术调研】三维(0)-webGL、三维基础知识、前置知识、数学知识以及简单示例

news2024/9/20 22:49:13

前言

​ 因业务需要了解网页端三维相关技术,故对webGL相关技术学习并记录。旨在了解网页端三维的基本原理。

什么是webGL?

​ WebGL全称叫做Web Graphics Library,它是JavaScript API。用于在任何兼容的Web浏览器中渲染交互式的3D图形,并且无需使用插件。它基于 OpenGL ES 2.0(一个用于嵌入式系统的图形库),并与其他 Web 标准完全集成,使开发者能够利用 GPU 加速图形处理直接在网页上实现复杂的图形效果。

​ WebGL可以在网页上开发高性能的3D游戏,许多现代网页游戏都利用了WebGL实现了丰富的图形效果和流畅的用户体验。

WebGL地解决了现有的Web交互式三维动画的两个问题:第一,它通过HTML脚本本身实现Web交互式三维动画的制作,无需任何浏览器插件支持;第二,它利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的OpenGL接口实现的。

​ 简单地说,webGL是一个用于在html中实现三维动画的API。

webGL坐标系

​ 在WebGL中,坐标系使用的是右手坐标系,手掌朝向自己大拇指与食指垂直,食指与中指垂直形成一个空间。大拇指方向是X轴,食指方向是Y轴,中指方向是Z轴。

​ 注意,其中X、Y、Z轴正方向最大值都为1,负方向最大值都为-1。

在这里插入图片描述

canvas画布上的坐标

Canvas画布可以支持2D,也可以支持3D。但是2D和3D坐标方向是完全不同的。

  • 2D,坐标原点是canvas画布的左顶点,水平方向向右是X轴,竖直方向向下是Y轴。如图:

在这里插入图片描述

  • 3D,坐标原点是canvas画布的中心点,水平方向向右是X轴,竖直方向向上是Y轴,屏幕朝外方向是Z轴。如图:

    在这里插入图片描述

webGL渲染管线

- webGL是个状态机,需要先提前设置所有状态,通过DrawCall命令GPU顺着渲染管线来调用设置好的所有状态,最终获得Framebuffer
- 设置所有状态的过程都是在CPU上跑,DrawCall命令下的渲染管线是GPU上跑
- 渲染管线存在可编程阶段,可配置阶段,不可配置阶段,可选阶段等
- 不同厂商实现的渲染管线部分不同

在这里插入图片描述

总结:渲染管线实质上指的是一系列的绘制过程。

其他前置知识

canvas

canvas是 HTML5 提供的一个用于绘制图形的区域,它可以通过 JavaScript 动态地渲染图形内容。canvas 可用于绘制图形、动画、图表、游戏以及实时数据可视化等。具体绘制2D或者3D图形,取决于渲染上下文对象是2D还是3D。
获取渲染上下文

HTMLCanvasElement.getContext()方法用于返回绘图上下文对象,绘图上下文对象是2D上下文还是3D上下文取决于传入的参数。

//获取一个webGLRenderingContext三维的渲染上下文对象
const gl = canvas.getContext("webgl");
//获取一个CanvasRenderingContext2D二维的渲染上下文对象
const 2d = canvas.getContext("2d");

类型化数组

​ JavaScript的类型化数组是一种用于处理和操作二进制数据的对象,类型化数组在处理WebGL等需要高性能和大数据量操作的应用中非常有用。

​ 类型化数组和普通的JavaScript数组不同,类型化数组的每一个元素都是同一类型的二进制数据,这种类型在创建数组时就已经确定了。

​ 以下是常用的一些特定类型的类型化数组:

视图名称 元素大小(字节) 描述 等价的C语言类型
Int8Array 1 8位二进制补码有符号整数 signed char
Uint8Array 1 8位无符号整数 unsigned char
Uint8ClampedArray 1 8位无符号整数(对溢出做特殊处理) unsigned char
Int16Array 2 16位二进制补码有符号整数 short
Uint16Array 2 16位无符号整数 unsigned short
Int32Array 4 32位二进制补码有符号整数 int
Uint32Array 4 32位无符号整数 unsigned int
Float32Array 4 32位IEEE浮点数 float
Float64Array 8 64位IEEE浮点数 double

​ 关于类型化数组本文不展开介绍,要详细了解请点击

着色器

​ GLSL(OpenGL Shading Language)是一种用于编写图形着色器的编程语言。着色器是用于在图形处理单元(GPU)上执行特定图形处理任务的程序。通俗讲,着色器是画点的工具,一个图形是由无数个点组成的,每个点都有其自己的颜色。

着色器的类型

一个着色器就是一个绘制东西到屏幕上的函数,着色器有顶点着色器和片元着色器。

  • 顶点着色器:处理每个顶点的属性,如位置、法线、纹理坐标等。它的主要任务是将顶点从对象坐标系转换到屏幕坐标系,并传递其他顶点属性给片段着色器。
  • 片元着色器:处理每个像素的颜色。它接收来自顶点着色器插值后的数据,并最终决定每个像素的颜色。
着色器语法

在HTML中,如果你想把着色器代码直接写在

		<!--  顶点着色器  -->
		<script id="vertex-shader" type="x-shader/x-vertex">
			attribute vec2 position;
			void main(){
   
				gl_PointSize = 5.0;
				gl_Position = vec4(position,0.0,1.0);
			}
		</script>
		
		<!--  片元着色器  -->
		<script id="fragment-shader" type="x-shader/x-fragment">
			void main(){
   
				gl_FragColor = vec4(1.0,0.0,0.0,1.0);
			}
		</script>
着色器中的变量修饰符
  • atrribute:用于顶点着色器,定义从顶点缓冲区传入的变量(只能在顶点缓冲区使用,可理解为用于传递顶点数据)
  • uniform:定义在整个渲染过程中保持不变的变量,常用于传递变换矩阵、光照参数。
  • varying:用于在点点着色器和片元着色器之间传递插值数据
着色器中的内部变量
  • 顶点着色器:
    • gl_Position 顶点的位置
    • gl_PointSize 顶点的大小
  • 片元着色器:
    • gl_FragColor 片元的最终颜色

webGL API

​ 见webGL API

线性代数、矩阵知识

​ 略。复习可参考以下:矩阵知识复习

第一个webGL程序

​ 绘制一个点。具体步骤见代码中注释:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>firstwebGLDemo</title>
		<style type="text/css">
			#myCanvas{
     
				background-color: aqua;
			}
		</style>
		<script>
			
			
		</script>
	</head>
	<body>
		<canvas id='myCanvas' width="700" height='600'></canvas>
		
		<!--  顶点着色器  -->
		<script id="vertex-shader" type="x-shader/x-vertex">
			void main(){
     
				gl_PointSize = 50.0;
				gl_Position = vec4(0.5,0.5,0.0,1.0);
			}
		</script>
		
		<!--  片元着色器  -->
		<script id="fragment-shader" type="x-shader/x-fragment">
			void main(){
     
				gl_FragColor = vec4(1.0,0.0,0.0,1.0);
			}
		</script>
		
		<script>
			/** 
			 * 	第一步 创建画布、获取画布、创建三维上下文对象	
			**/
			const canvas = document.getElementById("myCanvas");
			//获取一个webGLRenderingContext三维的渲染上下文对象
			const gl = canvas.getContext("webgl");	

			/** 
			 * 	第二步 创建着色器、与webGL渲染对象绑定、编译
			**/ 
			//通过element获取着色器源码
			const vertexSource = document.getElementById("vertex-shader").innerText;
			const fragmentSource = document.getElementById("fragment-shader").innerText;
			//创建顶点着色器对象,并绑定源码,编译;
			const vertexShader = gl.createShader(gl.VERTEX_SHADER);
			gl.shaderSource(vertexShader,vertexSource)
			gl.compileShader(vertexShader);
			//创建片元着色器对象,并绑定源码,编译
			const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
			gl.shaderSource(fragmentShader,fragmentSource);
			gl.compileShader(fragmentShader);
			
			
			/**
			 * 	第三步 创建着色器程序对象,并将着色器附着在程序上。
			**/
			//创建程序对象
			const program = gl.createProgram();
			//将着色器附着到程序对象
			gl.attachShader(program,vertexShader);
			gl.attachShader(program,fragmentShader);
			//webgl对象链接程序对象,将顶点着色器和片元着色器链接成一个完成的可执行程序
			gl.linkProgram(program);
			//webgl对象使用这个program作为渲染程序
			gl.useProgram(program);
			
			
			/**
			 *  第四步 绘制---点
			 */
			gl.drawArrays(gl.POINTS,0,1);
		</script>
	</body>

</html>

绘制线(使用attribute)

​ 根据第一个程序可知,绘制两个点后连接即可成为线。那么如何绘制多个点以及连接呢?这时候就要用到attribute(用于顶点着色器,定义从顶点缓冲区传入的变量,只能在顶点缓冲区使用,可理解为用于传递顶点数据)。

​ 代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>firstwebGLDemo</title>
		<style type="text/css">
			#myCanvas{
     
				background-color: aqua;
			}
		</style>
		<script>
			
			
		</script>
	</head>
	<body>
		<canvas id='myCanvas' width="700" height='600'></canvas>
		
		<!--  顶点着色器  -->
		<script id="vertex-shader" type="x-shader/x-vertex">
			attribute vec2 position;
			void main(){
     
				gl_PointSize = 5.0;
				gl_Position = vec4(position,0.0,1.0);
			}
		</script>
		
		<!--  片元着色器  -->
		<script id="fragment-shader" type="x-shader/x-fragment">
			void main(){
     
				gl_FragColor = vec4(1.0,0.0,0.0,1.0);
			}
		</script>
		
		<script>
			/** 第一步 创建画布、获取画布、创建三维上下文对象  **/
			const canvas = document.getElementById("myCanvas");
			//获取一个webGLRenderingContext三维的渲染上下文对象
			const gl = canvas.getContext("webgl");
			//获取一个CanvasRenderingContext2D二维的渲染上下文对象
			// const 2d = canvas.getContext("2d");
			
			/** 第一步 创建顶点并将顶点数据存到当前绑定的webGL缓冲区  **/
			const vertices = new Float32Array([
				0.0,0.5,
				-0.5,-0.5,
				0.5,-0.5,
				0.0,0.7,
				 -0.7,-0.7,
				0.7,-0.7
			])
			//创建了一个新的缓冲区对象,存储顶点数据、颜色数据等信息。
			const buffer = gl.createBuffer();
			//将之前创建的缓冲区对象绑定到当前的 WebGL 上下文。
			//gl.ARRAY_BUFFER表示我们绑定的是一个顶点属性的缓冲区,例如顶点位置、纹理坐标等。绑定后,所有针对 gl.ARRAY_BUFFER 的操作都会影响到这个缓冲区对象。			//
			gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
			//将数据传递到刚才绑定的缓冲区中
			//gl.STATIC_DRAW 是一个使用提示,告诉 WebGL 该数据将不会频繁更改,通常用于静态绘图。它帮助 WebGL 对数据进行优化
			gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW)
			
			
			/** 
			 * 	第三步 定义顶点着色器、片元着色器源码
			 * 
			 * 	attribute 用于顶点着色器,定义从顶点缓冲区传入的变量
			 * 	attribute vec2 position 声明一个名为position的顶点属性,它是一个二维向量
			 * 
			 * 	void main() {}:顶点着色器的主函数,计算每个顶点的最终位置。
			 *  vec4(positoin,0.0,1.0) 是一个四维向量,表示顶点的最终位置
			 * 	gl_FragColor = vec4(1.0,0.0,0.0,1.0); 将片元着色器设置为红色,使用vec4表示颜色,RGBA分别为(1.0,0.0,0.0,1.0)
			 *
			**/
			
			//模板引擎方式
			// const vertexShaderSource =`
			// 	attribute vec2 position;
			// 	void main(){
     
			// 		gl_Position = vec4(position,0.0,1.0);
					
			// 	}
			// `;
			
			// const fragmentShaderSource = `
			// 	void main(){
     
			// 		gl_FragColor = vec4(1.0,0.0,0.0,1.0);
			// 	}
			// `;
			
			//通过element获取
			const vertexSource = document.getElementById("vertex-shader").innerText;
			const fragmentSource = document.getElementById("fragment-shader").innerText;
			
			/**
			 * 	第四步 创建顶点着色器对象,并绑定源码,编译;创建片元着色器对象,并绑定源码,,编译
			 *  createShader(gl.VERTEX_SHADER) 创建一个顶点着色器
			 *  createShader(gl.FRAGMENT_SHADER) 创建一个片元着色器
			 *  gl.shaderSource(vertexShader,vertexSource) 将对应的着色器源码绑定到对应的着色器对象
			 *  gl.compileShader(vertexShader) 编译对应的着色器源码
			**/
			const vertexShader = gl.createShader(gl.VERTEX_SHADER);
			gl.shaderSource(vertexShader,vertexSource)
			gl.compileShader(vertexShader);
			const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
			gl.shaderSource(fragmentShader,fragmentSource);
			gl.compileShader(fragmentShader);
			
			
			/**
			 * 	第五步 创建着色器程序对象,并将着色器附着在程序上。
			 * 
			**/
			//创建程序对象
			const program = gl.createProgram();
			//将着色器附着到程序对象
			gl.attachShader(program,vertexShader);
			gl.attachShader(program,fragmentShader);
			//webgl对象链接程序对象,将顶点着色器和片元着色器链接成一个完成的可执行程序
			gl.linkProgram(program);
			//webgl对象使用这个program作为渲染程序
			gl.useProgram(program);
			
			
			/**
			 *  第六步 设置顶点属性
			 */
			//获取顶点属性position在着色器中的程序位置
			const positionLocation = gl.getAttribLocation(program,"position");
			//启用顶点属性数组
			gl.enableVertexAttribArray(positionLocation);
			/**
			 *  gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
			 *  指定顶点数据组的解析方式。
			 *  index:positionLocation 顶点属性position的位置,可以理解为需要将缓冲区数据解析到程序中的哪个位置。通过前面getAttribLocation返回的结果可以看出这是一个整数,指定要修改的顶点属性的索引。它通常是通过调用 
			 *  size:2 每个顶点属性的元素数量,可以理解为从缓冲区取数据时几个数据表示一个点。通过gl_Position = vec4(position,0.0,1.0)可以看出是二维数组,即两个浮点数表示一个点,所以是2.
			 *  type:gl.FlOAT 指定数组中每个组件的数据类型。在这个例子中,gl.FLOAT 表示每个顶点属性数据的类型为 32 位浮点数 (float)
			 *  normalized:false 数据是否应该被标准化处理。这里设置false表示不进行标准化处理,按原值传递。
			 *  stride:0 跨度:在缓冲区获取数据时的跨度,以字节为单位。如果数据连续则跨度为0。WebGL 会根据 size 和 type 自动计算跨度。例如,如果每个顶点都有 (x, y) 坐标,且每个坐标为 32 位浮点数,则步幅为 2 * 4 = 8 字节。
			 *  offset:0  指定缓冲区中的起始位置偏移量,以字节为单位。可以理解为从缓冲区的哪个字节位置开始读取第一个顶点属性。
			 */
			gl.vertexAttribPointer(positionLocation,2,gl.FLOAT,false,0,0);
			
			/**
			 *  第七步 绘制
			 * 
			 * gl.clearColor(0.0,0.0,0.0,1.0) 设置 WebGL 的清屏颜色,也就是背景颜色;
			 * gl.clear(gl.COLOR_BUFFER_BIT) 清除颜色缓冲区,也就是将整个绘图区域用前面指定的清屏颜色(黑色)填充;
			 * 以上与绘制内容无关,可以注释掉查看效果
			 * gl.drawArrays(gl.TRIANGLES,0,3) 绘制三角形,
			 *   gl.TRIANGLES 表示每三个顶点组成一个三角形。如果你有 6 个顶点,则 WebGL 会绘制两个三角形,依此类推。
			 * 	 0: 从顶点数组的第 0 个位置开始绘制。
			 *   3: 表示要绘制的顶点数量。可以理解为有效顶点数据 这里设置5表示5个点有效,即只能绘制出一个三角形
			 * 
			 * gl.POINTS: 绘制一系列点。
			 * gl.LINE_STRIP: 绘制一个线条。即,绘制一系列线段,上一点连接下一点。
			 * gl.LINE_LOOP: 绘制一个线圈。即,绘制一系列线段,上一点连接下一点,并且最后一点与第一个点相连。
			 * gl.LINES: 绘制一系列单独线段。每两个点作为端点,线段之间不连接。
			 * gl.TRIANGLE_STRIP:绘制一个三角带。
			 * gl.TRIANGLE_FAN:绘制一个三角扇。
			 * gl.TRIANGLES: 绘制一系列三角形。每三个点作为顶点。
			 * 
			 */
			// gl.clearColor(0.0,0.0,0.0,1.0);
			// gl.clear(gl.COLOR_BUFFER_BIT);
			// gl.drawArrays(gl.POINTS,0,6);
			// gl.drawArrays(gl.TRIANGLES,0,6);
			gl.drawArrays(gl.LINE_LOOP,0,6);
			gl.drawArrays(gl.LINE_LOOP,4,3);
		</script>
	</body>
	

	

</html>

绘制不同颜色的图形(使用varying)

​ 顶点着色器与片元着色器通过varying定义参数后传递参数。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>firstwebGLDemo</title>
		<style type

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

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

相关文章

参会邀请 | 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议&#xff08;MVIPIT 2024&#xff09;将于2024年9月13日-15日在中国张家口召开。 MVIPIT 2024聚焦机器视觉、图像处理与影像技术&#xff0c;旨在为专家、学者和研究人员提供一个国际平台&#xff0c;分享研究成果&#xff0c;讨论…

上海大学《2022年836+915自动控制原理真题及答案》 (完整版)

Part1&#xff1a;2022年上海大学真题题目 学硕836 专硕915 Part2&#xff1a;2022年上海大学真题答案 学硕836 专硕915

Linux学习之路 -- 线程概念

本文主要介绍线程的相关概念与基础控制 什么是线程&&线程的相关知识 按照书本上的定义&#xff0c;线程就是进程内部的一个执行分支&#xff0c;而线程是cpu调度的基本单位。 如果直接按照书本上的定义理解&#xff0c;线程这个概念是比较模糊的&#xff0c;而且我们…

013.Python爬虫系列_re正则解析

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数…

SAP学习笔记 - 开发01 - BAPI是什么?通过界面和ABAP代码来调用BAPI

BAPI作为SAP中的重要概念&#xff0c;在SAP系统的开发中几乎是必须的。 本章来学习一下BAPI 的直观印象&#xff0c;以及在ABAP代码中的调用。 目录 1&#xff0c; BAPI概述 1&#xff0c;从画面角度来直观体验一下BAPI 1-1&#xff0c;MM&#xff1a;購買依頼変更BAPI - …

日志服务管理

系统日志管理 sysklogd 系统日志服务 在 CentOS5 以及之前的发行版中&#xff0c;其采用的 sysklogd 服务来记录和管理系统日志的。 sysklogd 服务有两个模块&#xff1a; klogd&#xff1a; 用于记录 linux kernel 相关的日志 syslogd&#xff1a;用于记录用户空间应用日志…

OCC开发_箱梁梁体建模

概述 OCC(全称OpenCascade)是一个近年来比较受欢迎的开源三维CAD建模平台&#xff0c;曲线、曲面、实体、渲染等方面功能强大&#xff0c;并且在机械、航空、船舶等许多领域应用广泛。基于OCC的强大功能考虑&#xff0c;本人尝试将其引入桥梁领域。桥梁设计中&#xff0c;比较常…

Nginx核心配置文件结构

一、简单介绍 源码安装的Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf yum安装的Nginx的核心配置文件默认是放在/etc/nginx/nginx.conf 使用命令&#xff1a;nginx -t&#xff0c;可以检查测试nginx的配置文件&#xff08;nginx.conf&#xff09;语法是否…

6.1排序——插入排序与希尔排序

本篇博客来梳理两种常见排序算法&#xff1a;插入排序与希尔排序 常见的排序算法如图 写排序算法的原则&#xff1a;先写单趟&#xff0c;再写整体 一、直接插入排序 1&#xff0e;算法思想 先假定第一个数据有序&#xff0c;把第二个数据插入&#xff1b;再假设前两个数据…

iOS剪贴板同步到Windows剪贴板(无需安装软件的方案)

摘要 剪贴板同步能够提高很多的效率&#xff0c;免去复制、发送、复制、粘贴的步骤&#xff0c;只需要在手机上复制&#xff0c;就可以直接在电脑上 ctrlv 粘贴&#xff0c;这方面在 Apple 设备中是做的非常好的&#xff0c;Apple 设备之间的剪贴板同步功能&#xff08;Univer…

2024整理 iptables防火墙学习笔记大全_modepro iptables

Iptables名词和术语 2iptables表&#xff08;tables&#xff09;和链&#xff08;chains&#xff09; 2表及其链的功能 2  Filter表 2  NAT表 2  MANGLE表 2iptables的工作流程 3iptables表和链的工作流程图 3 二、 iptables实战应用 4iptables命令参数详解 4  iptable…

Python基础part1

Python基础 语法 字面量 数字 整数浮点复数布尔 字符串列表 list元组 Tuple集合 Set字典 Dictionary 注释 单行# 单行注释的内容多行“”“ 多行注释的内容 ”“” 单行注释#后要加一个空格再写注释 变量 变量无类型&#xff0c;但数据有类型 语法&#xff1a; 变量名 …

java黑马微项目

1 飞机票 代码实现&#xff1a; import java.util.Scanner; public class F1 {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.print("请输入票价&#xff1a; ");double jia input.nextDouble();System.out.print(&…

培训第九周(部署k8s基础环境)

一、前期系统环境准备 1、关闭防火墙与selinux [rootk8s-master ~]# systemctl stop firewalld[rootk8s-master ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.Removed symlink /etc/systemd/system/dbus-o…

快速格式化和格式化的区别有哪些?

磁盘通常需要格式化才能正常使用&#xff0c;通过格式化&#xff0c;磁盘结构才能被操作系统正确识别。磁盘格式化分为快速格式化和格式化&#xff08;完全格式化&#xff09;&#xff0c;它们都是格式化的方法&#xff0c;下面是它们的详细区别。 磁盘快速格式化和格式化的区别…

2024 年高教社杯全国大学生数学建模竞赛B题第三问详细解题思路(终版)

示例代码&#xff1a; import numpy as np import pandas as pd# 参数设定 params {m: 8, # 零配件数量n: 2, # 半成品数量p: [0.10, 0.10, 0.10, 0.10, 0.10, 0.10, 0.10, 0.10], # 零配件次品率c: [2, 8, 12, 2, 8, 12, 8, 12], # 购买单价d: [1, 1, 2, 1, 1, 2, 1, 2]…

个性化阅读体验:Spring Boot驱动的图书推荐系统

1 绪论 1.1研究背景 随着网络不断的普及发展&#xff0c;图书个性化推荐系统依靠网络技术的支持得到了快速的发展&#xff0c;首先要从学生的实际需求出发&#xff0c;通过了解学生的需求开发出具有针对性的首页、图书信息、好书推荐、留言反馈、个人中心、后台管理功能&#x…

文本分类场景下微调BERT

How to Fine-Tune BERT for Text Classification 论文《How to Fine-Tune BERT for Text Classification?》是2019年发表的一篇论文。这篇文章做了一些实验来分析了如何在文本分类场景下微调BERT&#xff0c;是后面网上讨论如何微调BERT时经常提到的论文。 结论与思路 先来看…

19:HAL—-DAC

一&#xff1a;介绍 1&#xff1a;简历 2&#xff1a;简图 F1,F4,F7的DAC框架图都一样。 触发源&#xff1a; 宏定义补全及解释 #define DAC_TRIGGER_NONE 0x00000000UL /*!< 转换是自动的&#xff0c;一旦DAC1_DHRxxxx寄存器被加载&#xff0c;不由外部触发 */ #define …

ctfshow-php特性(web123-web150plus)

​web123 <?php error_reporting(0); highlight_file(__FILE__); include("flag.php"); $a$_SERVER[argv]; $c$_POST[fun]; if(isset($_POST[CTF_SHOW])&&isset($_POST[CTF_SHOW.COM])&&!isset($_GET[fl0g])){if(!preg_match("/\\\\|\/|\~|…