WebGL 概念和基础入门

WebGL 概念和基础入门

WebGL 是什么

对于 WebGL 百度百科给出的解释是 WebGL 是一种 3D 绘图协议,而对此维基百科给出的解释却是一种 JavaScript API。由于 WebGL 技术旨在帮助我们在不使用插件的情况下在任何兼容的网页浏览器中开发交互式 2D 和 3D 网页效果,我们可以将其理解为一种帮助我们开发 3D 网页的绘图技术,当然底层还是 JavaScript API。

WebGL 发展史

WebGL 的发展最早要追溯到 2006 年,WebGL 起源于 Mozilla 员工弗拉基米尔·弗基西维奇的一项 Canvas 3D 实验项目,并于 2006 年首次展示了 Canvas 3D 的原型。这一技术在 2007 年底在 FireFox 和 Opera 浏览器中实现。2009 年初 Khronos Group 联盟创建了 WebGL 的工作组最初的工作成员包括 Apple、Google、Mozilla、Opera 等。 2011 年 3 月 WebGL 1.0 规范发布,WebGL 2 规范的发展始于 2013 年,并于 2017 年 1 月最终完成,WebGL 2 的规范,首度在 Firefox 51、Chrome 56 和 Opera 43 中被支持。

WebGL 中的基本概念

WebGL 运行在电脑的 GPU 中,因此需要使用能在 GPU 上运行的代码,这样的代码需要提供成对的方法,每对方法中的一个叫顶点着色器而另外一个叫做片元着色器,并且使用 GLSL 语言。将顶点着色器和片元着色器连接起来的方法叫做着色程序。

  • 顶点着色器 顶点着色器的作用是计算顶点的位置,即提供顶点在裁剪空间中的坐标值
    在这里插入图片描述

此块内容参考文章webglfundamentals

  • 片元着色器 片元着色器的作用是计算图元的颜色值,我们可以将片元着色器大致理解成网页中的像素
  • 数据获取方式 在前面我们提到了顶点着色器和片元着色器的概念,而顶点着色器和片元着色器这两个方法的运行都需要有对应的数据,接下来我们一起来了解一下着色器获取数据的四种方式:
    • 属性和缓冲 缓冲是发送到 GPU 的一些二进制数据序列,通常情况下缓冲数据包括位置、方向、纹理坐标、顶点颜色值等。 当然你可以根据自己的需要存储任何你想要的数据。 属性用于说明如何从缓冲中获取所需数据并将它提供给顶点着色器。
    • 全局变量 全局变量在着色程序运行前赋值,在运行过程中全局有效。全局变量在一次绘制过程中传递给着色器的值都一样。
    • 纹理 纹理是一个数据序列,可以在着色程序运行中随意读取其中的数据。一般情况下我们在纹理中存储的大都是图像数据,但你也可以根据自己喜欢存放除了颜色数据以外的其它数据
    • 可变量 可变量是一种顶点着色器给片元着色器传值的方式

小结

WebGL 只关心两件事:裁剪空间中的坐标值和颜色值。使用 WebGL 只需要给它提供这两个东西。 因此我们通过提供两个着色器来做这两件事,一个顶点着色器提供裁剪空间坐标值,一个片元着色器提供颜色值。

WebGL 工作原理

了解完 WebGL 的一些基本概念,我们可以一起来看看 WebGL 在 GPU 上的工作都做了些什么。正如我们之前了解到的 WebGL 在 GPU 上的工作主要分为两个部分,即顶点着色器所做的工作(将顶点转换为裁剪空间坐标)和片元着色器所做的工作(基于顶点着色器的计算结果绘制像素点)。假如我们需要绘制一个三角形,此时 GPU 上进行的工作便是先调用三次顶点着色器计算出三角形的 3 个顶点在裁剪空间坐标系中的对应位置,并通过变量 gl_Position 保存在 GPU 中,然后调用片元着色器完成每个顶点颜色值的计算,并通过变量 gl_FragColor 将对应的颜色值存储在 GPU 中。完成这些工作后我们已经得到了绘制三角形所需的像素点,最后便是光栅化三角形了。

原生 WebGL API 绘制三角形

前面我们已经学习了 WebGL 的发展史、基本概念和工作原理等内容,接下来我们就该实践出真知了,所以我们来看看如何通过 WebGL 在网页中绘制一个简单的三角形。我们知道 WebGL 作为一种 3D 绘图技术本身就是依托于 HTML5 中的 canvas 元素而存在的,所以再正式开始绘制之前我们需要进行一系列的准备工作:

  • 首先我们需要创建一个 canvas 元素作为绘制三角形所需的画布,并完成浏览器对 canvas 元素兼容性的测试。

    function webglInit () {const canvasEl = document.createElement('canvas'); // canvas 元素创建canvasEl.width = document.body.clientWidth; // 设置 canvas 画布的宽度canvasEl.height = document.body.clientHeight; // 设置 canvas 画布的高度document.body.append(canvasEl); // 将创建好的 canvas 画布添加至页面中的 body 元素下// 接下来我们需要判断浏览器对于 WebGL 的兼容性,如果浏览器不支持 WebGL 那么我们就不需要再进行下去了if(!canvasEl.getContext("webgl") && !canvasEl.getContext("experimental-webgl ")) {alert("Your Browser Doesn't Support WebGL");return;}// 如果浏览器支持 WebGL,那么我们就获取 WebGL 的上下文对象并复制给变量 glconst context = (canvasEl.getContext("webgl"))? canvasEl.getContext("webgl") : getContext("experimental-webgl");/* 设置视口 context.viewport(x, y, width, height);x: 用来设定视口的左下角水平坐标。默认值:0y: 用来设定视口的左下角垂直坐标。默认值:0width: 用来设定视口的宽度。默认值:canvas 的宽度height: 用来设定视口的高度。默认值:canvas 的高度当你第一次创建 WebGL 上下文的时候,视口的大小和 canvas 的大小是匹配的。然而,如果你重新改变了canvas的大小,你需要告诉 WebGL 上下文设定新的视口,因此这里作为初次创建这行代码可以省略*/context.viewport(0, 0, context.canvas.width, context.canvas.height);return context;
    }
    
  • 准备好了 canvas 画布下一步就可以开始画三角形了,正如我们平常画画一般,我们需要准备画三角形所需的顶点即顶点着色器,以及三角形对应的填充色即片元着色器

    const gl =  webglInit();
    // 创建顶点着色器 语法 gl.createShader(type) 此处 type 为枚举型值为 gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER 两者中的一个
    const vShader = gl.createShader(gl.VERTEX_SHADER) 
    // 编写顶点着色器的 GLSL 代码 语法 gl.shaderSource(shader, source); shader - 用于设置程序代码的 webglShader(着色器对象) source - 包含 GLSL 程序代码的字符串
    gl.shaderSource(vShader, `attribute vec4 v_position;void main() {gl_Position = v_position; // 设置顶点位置}
    `)
    gl.compileShader(vShader) // 编译着色器代码const fShader = gl.createShader(gl.FRAGMENT_SHADER) 
    gl.shaderSource(fShader, `precision mediump float;uniform vec4 f_color;void main() {gl_FragColor = f_color; // 设置片元颜色}
    `) // 编写片元着色器代码 
    gl.compileShader(fShader) // 编译着色器代码
    
  • 前面我们已经完成了顶点着色器和片元着色器的配置,做好了一切绘制前的准备工作接下来,接下来我们就需要创建一个程序用来连接我们的顶点着色器和片元着色器完成最终的三角形绘制工作。

// 创建一个程序用于连接顶点着色器和片元着色器
const program = gl.createProgram() 
gl.attachShader(program, vShader) // 添加顶点着色器
gl.attachShader(program, fShader) // 添加片元着色器
gl.linkProgram(program) // 连接 program 中的着色器gl.useProgram(program) // 告诉 WebGL 用这个 program 进行渲染const color = gl.getUniformLocation(program, 'f_color') 
// 获取 f_color 变量位置
gl.uniform4f(color, 0.93, 0, 0.56, 1) // 设置它的值const position = gl.getAttribLocation(program, 'v_position') 
// 获取 v_position 位置
const pBuffer = gl.createBuffer() 
// 创建一个顶点缓冲对象,返回其 id,用来放三角形顶点数据,
gl.bindBuffer(gl.ARRAY_BUFFER, pBuffer) 
// 将这个顶点缓冲对象绑定到 gl.ARRAY_BUFFER
// 后续对 gl.ARRAY_BUFFER 的操作都会映射到这个缓存
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5,0.5, 0,-0.5, -0.5
]),  // 三角形的三个顶点// 因为会将数据发送到 GPU,为了省去数据解析,这里使用 Float32Array 直接传送数据
gl.STATIC_DRAW // 表示缓冲区的内容不会经常更改
)
// 将顶点数据加入的刚刚创建的缓存对象gl.vertexAttribPointer( // 告诉 OpenGL 如何从 Buffer 中获取数据position, // 顶点属性的索引2, // 组成数量,必须是 1,2,3 或 4。我们只提供了 x 和 ygl.FLOAT, // 每个元素的数据类型false, // 是否归一化到特定的范围,对 FLOAT 类型数据设置无效0, // stride 步长 数组中一行长度,0 表示数据是紧密的没有空隙,让 OpenGL 决定具体步长0 // offset 字节偏移量,必须是类型的字节长度的倍数。
)
gl.enableVertexAttribArray(position);
// 开启 attribute 变量额,使顶点着色器能够访问缓冲区数据gl.clearColor(0, 1, 1, 1) // 设置清空颜色缓冲时的颜色值
gl.clear(gl.COLOR_BUFFER_BIT) // 清空颜色缓冲区,也就是清空画布
// 语法 gl.drawArrays(mode, first, count); mode - 指定绘制图元的方式 first - 指定从哪个点开始绘制 count - 指定绘制需要使用到多少个点
gl.drawArrays( gl.TRIANGLES, 0, 3 )

配合 HTML 文件运行上述代码后我们可以在网页中看到如图所示的三角形,且三角形大小根据浏览器窗口大小自适应。
在这里插入图片描述

可以看到仅仅是绘制一个简单的三角形我们就已经写了一大长串的 JS 代码,如果真的用原生 WebGL API 编写一个动态的 3D 交互式网页,那么开发成本可见是极其昂贵的。

WebGL 原生 API 开发的不足

上面原生 WebGL API 绘制三角形的例子,充分向我们展示了使用原生 WebGL API 开发 3D 交互式网页存在的问题。尽管从功能上而言原生 WebGL API 可以满足我们任意场景的开发需要但是,其开发和学习的成本极其昂贵。对于 WebGL 的初学者而言是极度不友好的,我们需要配置顶点着色器用于计算绘制顶点所在的位置,而这对于开发者而言需要一定的数学基础熟悉矩阵的运算,同时也要有空间几何的概念熟悉 3D 物体的空间分布。而场景的光照,纹理等的设计也都需要对颜色的配置有自己的见解。所以为了给初学者降低难度,下面我将介绍一些 WebGL 开发的常用框架。

几种 WebGL 开发的框架

  • Three.js
    • Three.js 是 WebGL 的综合库,其应用范围比较广泛,美中不足的一点是,Three.js 库没有比较全面详细的官方文档,对于使用者而言不是特别友好
  • Cesium.js
    • Cesium.js 是专用于 3D 地图开发的 WebGL 库,其拥有较为全面的 3D 地图开发 API,对于需要开发 3D 地图的开发者而言是一个不错的选择,但针对其他场景的应用开发覆盖的就不是很全面了
  • Babylon.js
    • Babylon.js 是一款国外应用较广泛的 WebGL 库,感兴趣的小伙伴可以自己去了解一下,这里就不做详细介绍了

Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,同时 Three.js 也是一个综合性的 WebGL 库。如果你需要进行 3D 地图网页的开发那就可以用到 Cesium.js 了,Cesium.js 是一款专用于地图开发的 WebGL 库。而 Babylon.js 则是国外较火的 WebGL 库。

基于 Three.js 绘制旋转立方体

  • 运用 Three.js 绘制旋转立方体的第一步同原生 WebGl 一样,首先便是要准备 Three.js 运行所需的环境。

    // 创建 renderer 变量用于存储渲染器对象
    var renderer;
    // initThree 函数用来初始化 Three.js 运行所需的环境
    function initThree() {// 同原生 WebGL 环境搭建过程一样,Three.js 也需要先设置画布 canvas 元素的大小width = document.getElementById('canvas-frame').clientWidth; // 设置宽度属性为浏览器窗口宽度height = document.getElementById('canvas-frame').clientHeight; // 设置高度属性为浏览器窗口高度// 新建一个 WebGL 渲染器并赋值给 renderer 变量renderer = new THREE.WebGLRenderer({antialias: true});// 设置画布大小为浏览器窗口大小renderer.setSize(width, height);// 将画布元素挂载到页面document.getElementById('canvas-frame').appendChild(renderer.domElement);// 设置清空画布的颜色为白色renderer.setClearColor(0xFFFFFF, 1.0);
    }
    
  • 接下来不同于原生 WebGL 需要准备顶点着色器和片元着色器,Three.js 需要准备的是相机。Three.js 绘制 3D 网页所需的 3 大基本要素便是 相机、场景和物体,当然如果有需要设置明暗效果我们还需要加入第 4 要素光源,光源并不一定需要设置,但是相机、场景和物体是一定有的。

    // 创建 camera 变量用于存储相机对象
    var camera;
    // 初始化相机函数 Three.js 中相机的类型有好几种可以根据具体需要进行选择这里我们要创建的是一个旋转的立方体所以采用的是透视相机,而如果需要创建 3D 阴影效果的场景则需要使用正交相机
    function initCamera() {/* 创建透一个视相机的实例语法 PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number ) fov - 视角aspect - 物体的长宽比near - 相机近点截图far - 相机远点截图*/camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);camera.position.x = 0; // 设置相机在三维空间坐标中 x 轴的位置camera.position.y = 10; // 设置相机在三维空间坐标中 y 轴的位置camera.position.z = 5; // 设置相机在三维空间坐标中 z 轴的位置camera.up.x = 0;camera.up.y = 0;camera.up.z = 1;camera.lookAt(new THREE.Vector3(0,0,0));// 设置相机的观察点
    }
    
  • 上一步我们完成了相机的设置,下面我们来准备 Three.js 绘制 3D 网页所需的第二要素场景。

    // 创建 scene 变量用于存储场景对象
    var scene;
    // initScene 函数创建一个场景并赋值给 scene 变量
    function initScene() {scene = new THREE.Scene();
    }
    
  • 准备好了相机和场景下面我们就需要设置拍摄的物体了,完成物体的绘制后将其添加到场景中。

    // 创建一个 cube 变量用于存放几何立方体
    var cube;// initObject 函数就是我们创建场景的核心了
    function initObject() {// 首先创建一个一个几何类的实例并赋值给 geometry 变量var geometry = new THREE.BoxGeometry(1, 1, 1); // 然后创建一种材质的实例 MeshBasicMaterial 材质的构造函数能够创建一种简单的不受场景灯光效果影响的材质var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );// Mesh 是一种三角形网格基本单元的构造函数,类似于我们原生 WebGL 中的片元着色器它用于连接几何体和材质cube = new THREE.Mesh( geometry, material );// 最后将创建好的几何立方体添加到场景中scene.add(cube);
    }
    
  • 到这里我们已经完成了 Three.js 绘制 3D 网页所需的基本配置,当然如果有需要对 3D 网页的明暗效果,灯光颜色做处理的我们还可以在场景中加入灯光的配置,这里由于我们的旋转立方体对于灯光并未有什么特殊的要求,所以我们便直接进入最后一步场景的渲染。

    // render 函数提供了浏览器的循环渲染功能
    function render() {cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
    }
    // 最后将 Threee.js 环境初始化,场景创建,相机创建渲染器创建以及渲染初始化等函数合成到一起执行我们就完成了一个旋转立方体的绘制
    function threeStart() {
    initThree();
    initCamera();
    initScene();
    initObject();
    render();
    }
    document.addEventListener('DOMContentLoaded',function(){threeStart();
    });
    
  • Three.js 的旋转立方体的绘制还需要配合 HTML 文件使用才能看到效果

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script type="text/javascript" src="../utils/three.js"></script><style type="text/css">div#canvas-frame {border: none;cursor: pointer;width: 100%;height: 600px;background-color: #EEEEEE;}</style>
    </head>
    <body><div id="canvas-frame"></div>
    </body>
    </html>
    

    配合 HTML 文件运行上述代码后我们可以在网页中看到,一个旋转的绿色立方体

在这里插入图片描述

小结

通过对比我们发现尽管我们通过 Three.js 创建了更为复杂的场景,但是代码量相对 WebGL 原生 API 绘制三角形时反而要少了。由此可见对于初学者而言,直接使用 WebGL 原生 API 进行 3D 网页的开发,显然是不合适的。这时候我们就可以借助像 Three.js 这样的 WebGL 封装库进行开发。相较之原生 API 的开发,这类第三方封装好的 WebGL 库大大降低了我们的开发成本,同时也能帮助我们开发出更加炫酷的页面效果。当然也不是说原生 API 不好,毕竟如果有能力学透 WebGL 原生 API 的开发还是能够帮助我们在开发 3D 网页的时候实现更加随心所欲的功能,且 Three.js 本身的文档并不是特别完善所以想要顺利的使用同样需要摸透 WebGL 原生 API。

总结

WebGL 技术出现的时间并不算短,然而尽管能够开发出拥有炫酷效果的 3D 网页却一直未能大火,现今应用的最多的也不过是 3D 网页游戏的开发。这其中很大一部分的原因便是受到网速发展的制约,在当今这个快节奏的社会中人们对于网页加载速度的忍耐度是极低的,一个 WebGL 开发的 3D 网页动辄需要三四秒的打开时间对用户而言无疑是极度不友好的。但是相信随着 5G 通信技术的发展,网络通信技术飞速发展下,WebGL 技术的明天可能会迎来新的发展契机。

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

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

相关文章

react 实现小球加入购物车动画

代码 import React, { useRef } from react;const ProductLayout () > {const box useRef(null);const createBall (left, top) > {const ball document.createElement(div);ball.style.position absolute;ball.style.left left - 10 px;ball.style.top top - 1…

【机器学习】了解 AUC - ROC 曲线

一、说明 在机器学习中&#xff0c;性能测量是一项基本任务。因此&#xff0c;当涉及到分类问题时&#xff0c;我们可以依靠AUC - ROC曲线。当我们需要检查或可视化多类分类问题的性能时&#xff0c;我们使用AUC&#xff08;曲线下面积&#xff09;ROC&#xff08;接收器工作特…

使用 Vue 创建一个简单的 Loading 动画

使用 Vue 创建一个简单的 Loading 动画 1. 开始之前 确保 正确安装了 Vue 3知道如何启动一个新的 Vue 项目&#xff08;或在项目中使用Vue&#xff09;了解 Vue 3 的 Composition API&#xff08;本文将使用&#xff09; 2. 设计组件 该组件应该包含三个部分 控制逻辑旋转…

win10 安装 langchain-chatglm 遇到的问题

win10 安装 langchain-chatglm 避坑指南&#xff08;2023年6月21日最新版本&#xff09;_憶的博客-CSDN博客官网看起来安装很简单&#xff0c;网上教程也是&#xff0c;但实际上我耗费了两天时间&#xff0c;查阅了当前网络上所有可查阅的资料&#xff0c;重复「安装-配置-卸载…

Spring Security 构建基于 JWT 的登录认证

一言以蔽之&#xff0c;JWT 可以携带非敏感信息&#xff0c;并具有不可篡改性。可以通过验证是否被篡改&#xff0c;以及读取信息内容&#xff0c;完成网络认证的三个问题&#xff1a;“你是谁”、“你有哪些权限”、“是不是冒充的”。 为了安全&#xff0c;使用它需要采用 …

HideSeeker论文阅读

文章目录 3.1 Overview of Our System HideSeeker3.2 Visual Information Extraction3.3 Relation Graph Learning3.4 Hidden Object Inference 4 EVALUATIONS4.7 Summary 6 DISCUSSIONS AND CONCLUSION 3.1 Overview of Our System HideSeeker 我们设计了一种名为“HideSeeke…

个人博客系统(SSM版 前端+后端)

前言 在学习Servlet的时候,也写了一个博客系统,主要的就是使用servelet加Tomcat进行实现的,而这个项目 仅仅适合去学习Web项目开发的思想,并不满足当下企业使用框架的思想,进行学习过Spring,Spring Boot,Spring MVC以及MyBatis之后,我们就可以对之前的项目使用SSM框架的形式进行…

react+redux异步操作数据

reactredux异步操作数据 redux中操作异步方法&#xff0c;主要是&#xff1a; 1、借助createAsyncThunk()封装异步方法&#xff1b;2、通过extraReducers处理异步方法触发后的具体逻辑&#xff0c;操作派生的state 1、异步操作的slice import { createSlice, createAsyncThunk…

uniapp 之 微信小程序、支付宝小程序 对于自定义导航栏的不同

目录 前言 微信小程序 代码 支付宝小程序 首页配置文件 二级菜单页面 配置 总结 不同 相同 前言 小程序都是 uni-app 写的 不是原生 微信小程序 代码 pages.json文件中配置 重点&#xff1a; "navigationStyle": "custom", // 导航栏样式…

ChatGPT开放自定义系统级别的指令,可设置偏好变成专属助理

OpenAI官方消息https://openai.com/blog/custom-instructions-for-chatgpt OpenAI为其大型语言模型接口ChatGPT引入了自定义指令&#xff0c;旨在为用户提供更加量身定制和个性化的体验&#xff0c;可以设置您的偏好&#xff0c;ChatGPT将在未来的所有对话中记住它们。 该功…

Python—数据结构(一)

先放一张自己学习和整理归纳的思维导图&#xff0c;以便让大家都知道我自己的整体学习路线。 数据结构的学习路上内容枯燥&#xff0c;但坚持下来一定有很大的收获&#xff01;加油&#x1f4aa;&#x1f3fb;&#xff01; 数据结构 数据的概念数据元素&#xff1a; 若干基本…

音视频开发-ffmpeg介绍-系列二

目录 一、FFmpeg核心结构体 二、解码流程 三、FFmpeg解码实现 四、FFmpeg编码实现 五、FFmpeg转码实现 一、FFmpeg核心结构体 AVFormatContext&#xff1a;解封装功能的结构体&#xff0c;包含文件名、音视频流、时长、比特率等信息&#xff1b; AVCodecContext&#xf…

【算法基础:数学知识】4.3 欧拉函数

文章目录 欧拉函数定义性质 例题列表873. 欧拉函数&#xff08;使用质因数分解求一个数的欧拉函数&#xff09;原理讲解&#xff08;公式推导&#xff09;⭐解法代码 874. 筛法求欧拉函数&#xff08;求 1 ~ n 中所有数字的欧拉函数&#xff09;⭐ 欧拉函数 https://oi-wiki.o…

[数据结构 -- 手撕排序算法第六篇] 递归实现快速排序(集霍尔版本,挖坑法,前后指针法为一篇的实现方法,很能打)

目录 1、常见的排序算法 1.1 交换排序基本思想 2、快速排序的实现方法 2.1 基本思想 3 hoare&#xff08;霍尔&#xff09;版本 3.1 实现思路 3.2 思路图解 3.3 为什么实现思路的步骤2、3不能交换 3.4 hoare版本代码实现 3.5 hoare版本代码测试 4、挖坑法 4.1 实现…

【手撕排序算法】---基数排序

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构初阶&#xff08;C实现&#xff09;】 我们直到一般的排序都是通过关键字的比较和移动这两种操作来进行排序的。 而今天介绍的…

​MySQL高阶语句(三)

目录 1、内连接 2、左连接 3、右连接&#xff1a; 二、存储过程⭐⭐⭐ 4. 调用存储过程 5.查看存储过程 5.1 查看存储过程 5.2查看指定存储过程信息 三. 存储过程的参数 3.1存储过程的参数 3.2修改存储过程 四.删除存储过程 MySQL 的连接查询&#xff0c;通常都是将来…

微服务一 实用篇 - 5.分布式搜索引擎(ElasticSearch基础)

《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 《微服务一 实用篇 - 5.分布式搜索…

【广州华锐互动】列车人员疏散VR虚拟演练系统

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐应用于各个领域。在火车站安全方面&#xff0c;为了提高旅客的安全意识和应对突发事件的能力&#xff0c;列车人员疏散VR虚拟演练系统应运而生。 列车人员疏散VR虚拟演练系统是一种基于虚拟现实技术的教育培训系统&…

【Vue】day03-VueCli(脚手架)

day03 一、今日目标 1.生命周期 生命周期介绍 生命周期的四个阶段 生命周期钩子 声明周期案例 2.综合案例-小黑记账清单 列表渲染 添加/删除 饼图渲染 3.工程化开发入门 工程化开发和脚手架 项目运行流程 组件化 组件注册 4.综合案例-小兔仙首页 拆分模块-局部…

SpringBoot 如何使用 MockMvc 进行 Web 集成测试

SpringBoot 如何使用 MockMvc 进行 Web 集成测试 介绍 SpringBoot 是一个流行的 Java Web 开发框架&#xff0c;它提供了一些强大的工具和库&#xff0c;使得开发 Web 应用程序变得更加容易。其中之一是 MockMvc&#xff0c;它提供了一种测试 SpringBoot Web 应用程序的方式&…