当前位置: 首页 > news >正文

WebGL 视图矩阵、模型视图矩阵

目录

立方体由三角形构成

视点和视线

视点、观察目标点和上方向

视点:

观察目标点:

上方向:

在WebGL中,观察者的默认状态应该是这样的:

视图矩阵程序(LookAtTriangles.js) 

 实际上,“根据自定义的观察者状态,绘制观察者看到的景象”与“使用默认的观察状态,但是对三维对象进行平移、旋转等变换,再绘制观察者看到的景象”,这两种行为是等价的。(归根结底:不论视图怎样变化,无疑就是旋转、平移等操作,最终本质上都是对物体进行相反方向的旋转平移(默认的视角))

移动视点和移动被观察对象等效

从指定视点观察旋转后的三角形

<旋转后顶点坐标>=<旋转矩阵>×<原始顶点坐标>

<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转后顶点坐标>

<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转矩阵>×<原始顶点坐标>

<视图矩阵>×<模型矩阵>×<原始顶点坐标>

模型视图矩阵程序(LookAtRotatedTriangles.js) 

模型视图矩阵

<模型视图矩阵>=<视图矩阵>×<模型矩阵>

<模型视图矩阵>×<顶点坐标>


立方体由三角形构成

三维物体也是由二维图形(特别是三角形)组成的。如下图所示,12个三角形组成了一个立方体。

既然三维物体是由三角形组成的,那么则需要逐个绘制组成物体的每个三角形,最终就可以绘制出整个三维物体了。但是,三维与二维还有一个显著区别:在绘制二维图形时,只需要考虑顶点的x和y坐标,而绘制三维物体时,还得考虑它们的深度信息(depth information)。那就开始吧,首先我们来研究一下如何定义三维世界的观察者:在什么地方、朝哪里看、视野有多宽、能看多远。

视点和视线

三维物体与二维图形的最显著区别就是,三维物体具有深度,也就是Z轴。因此,你会遇到一些之前不曾考虑过的问题。事实上,我们最后还是得把三维场景绘制到二维的屏幕上,即绘制观察者看到的世界,而观察者可以处在任意位置观察。为了定义一个观察者,你需要考虑以下两点:

● 观察方向,即观察者自己在什么位置,在看场景的哪一部分?

● 可视距离,即观察者能够看多远?

我们将观察者所处的位置称为视点(eye point),从视点出发沿着观察方向的射线称作视线(viewing direction)。本次将研究如何通过视点和视线来描述观察者。到下面我们再来研究“观察者能看多远”的问题。 

我们来创建一个新的示例程序LookAtTriangles。在程序中,视点位于(0.20,0.25,0.25),视线向着原点(0,0,0)方向,可以看到原点附近有三个三角形。程序中的这三个三角形前后错落摆放,以帮助你理解三维场景中深度的概念。下图显示了LookAtTriangles的运行结果。

视点、观察目标点和上方向

为了确定观察者的状态,你需要获取两项信息:视点,即观察者的位置;观察目标点(look-at point),即被观察目标所在的点,它可以用来确定视线。此外,因为我们最后要把观察到的景象绘制到屏幕上,还需要知道上方向(up direction)。有了这三项信息,就可以确定观察者的状态了。下面将逐一进行解释(见下图)。

视点:

观察者所在的三维空间中位置,视线的起点。在接下来的几节中,视点坐标都用(eyeX,eyeY,eyeZ)表示。 

观察目标点:

被观察目标所在的点。视线从视点出发,穿过观察目标点并继续延伸。注意,观察目标点是一个点,而不是视线方向,只有同时知道观察目标点和视点,才能算出视线方向。观察目标点的坐标用(atX,atY,atZ)表示。

上方向:

最终绘制在屏幕上的影像中的向上的方向。试想,如果仅仅确定了视点和观察点,观察者还是可能以视线为轴旋转的(如下图所示,头部偏移会导致观察到的场景也偏移了)。所以,为了将观察者固定住,我们还需要指定上方向。上方向是具有3个分量的矢量,用(upX,upY,upZ)表示。

在WebGL中,我们可以用上述三个矢量创建一个视图矩阵(view matrix),然后将该矩阵传给顶点着色器。视图矩阵可以表示观察者的状态,含有观察者的视点、观察目标点、上方向等信息。之所以被称为视图矩阵,是因为它最终影响了显示在屏幕上的视图,也就是观察者观察到的场景。根据提供的Matrix4.setLookAt()函数可以根据上述三个矢量:视点、观察点和上方向,来创建出视图矩阵 (矩阵库 WebGL矩阵变换库_山楂树の的博客-CSDN博客)。 

在WebGL中,观察者的默认状态应该是这样的:

● 视点位于坐标系统原点(0,0,0)。

● 视线为Z轴负方向,观察点为(0,0,-1)

如果将上方向改为X轴正半轴方向(1,0,0),你将看到场景旋转了90度。

创建这样一个矩阵,你只需要简单地使用如下代码(见下图)。

现在,你已经了解了setLookAt()函数,下面来看示例程序的代码。

视图矩阵程序(LookAtTriangles.js) 

程序显示了LookAtTriangles.js的代码,我们修改了视点,然后绘制了3个三角形,如上图三角形所示。实际上这3个三角形的颜色分别为蓝色到红色、黄色到红色和绿色到红色的渐变色。

var VSHADER_SOURCE ='attribute vec4 a_Position;\n' +'attribute vec4 a_Color;\n' +'uniform mat4 u_ViewMatrix;\n' +'varying vec4 v_Color;\n' +'void main() {\n' +'  gl_Position = u_ViewMatrix * a_Position;\n' +'  v_Color = a_Color;\n' +'}\n';var FSHADER_SOURCE ='#ifdef GL_ES\n' +'precision mediump float;\n' +'#endif\n' +'varying vec4 v_Color;\n' +'void main() {\n' +'  gl_FragColor = v_Color;\n' +'}\n';function main() {var canvas = document.getElementById('webgl');var gl = getWebGLContext(canvas);if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {console.log('Failed to intialize shaders.');return;}// 设置顶点坐标和颜色(蓝色三角形在最前面)var n = initVertexBuffers(gl);gl.clearColor(0, 0, 0, 1);// 获取u_ViewMatrix变量的存储地址var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');// 设置视点、视线和上方向var viewMatrix = new Matrix4();viewMatrix.setLookAt(0.20, 0.25, 0.25, 0, 0, 0, 0, 1, 0);// 将视图矩阵传给u_ViewMatrix变量gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);gl.clear(gl.COLOR_BUFFER_BIT);// 绘制三角形gl.drawArrays(gl.TRIANGLES, 0, n);
}function initVertexBuffers(gl) {var verticesColors = new Float32Array([// 顶点和坐标颜色0.0,  0.5,  -0.4,  0.4,  1.0,  0.4, // 绿色三角形在最后面-0.5, -0.5,  -0.4,  0.4,  1.0,  0.4,0.5, -0.5,  -0.4,  1.0,  0.4,  0.4, 0.5,  0.4,  -0.2,  1.0,  0.4,  0.4, // 黄色三角形在中间-0.5,  0.4,  -0.2,  1.0,  1.0,  0.4,0.0, -0.6,  -0.2,  1.0,  1.0,  0.4, 0.0,  0.5,   0.0,  0.4,  0.4,  1.0,  // 蓝色三角形在最前面-0.5, -0.5,   0.0,  0.4,  0.4,  1.0,0.5, -0.5,   0.0,  1.0,  0.4,  0.4, ]);var n = 9;// 创建缓冲区对象var vertexColorbuffer = gl.createBuffer();  gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorbuffer);gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);var FSIZE = verticesColors.BYTES_PER_ELEMENT;var a_Position = gl.getAttribLocation(gl.program, 'a_Position');gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, FSIZE * 6, 0);gl.enableVertexAttribArray(a_Position);var a_Color = gl.getAttribLocation(gl.program, 'a_Color');gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);gl.enableVertexAttribArray(a_Color);gl.bindBuffer(gl.ARRAY_BUFFER, null);return n;
}

首先,来看一下initVertexBuffers()函数(第42行)。verticesColors数组包含了3个三角形共计9个顶点的数据,而且顶点坐标的z分量也不再是0了。接着我们创建了缓冲区对象(第57行),并将数组中的数据填了进去(第58~59行)。此外,我们还把gl.drawArrays()的第3个参数改成了9(第39行),因为这里共有9个顶点。

然后,需要建立视图矩阵(包含了视点、视线和上方向信息)并传给顶点着色器。为此,我们先创建了一个Matrix4对象viewMatrix(第33行),然后用setLookAt()方法将其设置为视图矩阵(第34行),最后将视图矩阵中的元素传给顶点着色器中的u_ViewMatrix变量(第36行)。

 实际上,“根据自定义的观察者状态,绘制观察者看到的景象”与“使用默认的观察状态,但是对三维对象进行平移、旋转等变换,再绘制观察者看到的景象”,这两种行为是等价的。(归根结底:不论视图怎样变化,无疑就是旋转、平移等操作,最终本质上都是对物体进行相反方向的旋转平移(默认的视角))

举个例子,默认情况下视点在原点,视线沿着Z轴负方向进行观察。假如我们将视点移动到(0,0,1),如下图(左)所示。这时,视点与被观察的三角形在Z轴上的距离增加了1.0个单位。实际上,如果我们使三角形沿Z轴负方向移动1.0个单位,也可以达到同样的效果,因为观察者看上去是一样的,如下图(右)所示。

移动视点和移动被观察对象等效

事实上,上述过程就发生在示例程序LookAtTriangles.js中。根据视点、观察点和上方向参数,setLookAt()方法计算出的视图矩阵恰恰就是“沿着Z轴负方向移动1.0个单位”的变换矩阵。所以,把这个矩阵与顶点坐标相乘,就相当于获得了“将视点设置在(0.0,0.0,1.0)”的效果。视点移动的方向与被观察对象(也就是整个世界)移动的方向正好相反。对于视点的旋转,也可以采用类似的方式。 

“改变观察者的状态”与“对整个世界进行平移和旋转变换”,本质上是一样的,它们都可以用矩阵来描述。接下来,我们将从一个指定的视点来观察旋转后的三角形。

从指定视点观察旋转后的三角形

现在将修改LookAtTriangles程序来绘制一个从指定位置看过去的旋转后的三角形。这时,我们需要两个矩阵:旋转矩阵(表示三角形的旋转)和视图矩阵(表示观察世界的方式)。首先有一个问题是,以怎样的顺序相乘这两个矩阵。

我们知道,矩阵乘以顶点坐标,得到的结果是顶点经过矩阵变换之后的新坐标。也就是说,用旋转矩阵乘以顶点坐标,就可以得到旋转后的顶点坐标。

用视图矩阵乘以顶点坐标会把顶点变换到合适的位置,使得观察者(以默认状态)观察新位置的顶点,就好像在观察者处在(视图矩阵描述的)视点上观察原始顶点一样。现在要在某个视点处观察旋转后的三角形,我们需要先旋转三角形,然后从这个视点来观察它。换句话说,我们需要先对三角形进行旋转变换,再对旋转后的三角形进行与“移动视点”等效的变换。我们按照上述顺序相乘两个矩阵。具体看一下等式。

我们知道,如果想旋转图形,就需要用旋转矩阵乘以旋转前的顶点坐标:

<旋转后顶点坐标>=<旋转矩阵>×<原始顶点坐标>

用视图矩阵乘以旋转后的顶点坐标,就可以获得“从视点看上去”的旋转后的顶点坐标: 

<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转后顶点坐标>

将第1个式子代入第2个,可得:

<“从视点看上去”的旋转后顶点坐标>=<视图矩阵>×<旋转矩阵>×<原始顶点坐标>

除了旋转矩阵,你还可以使用平移、缩放等基本变换矩阵或它们的组合,这时矩阵被称为模型矩阵(model matrix)。这样,上式就可以写成:

<视图矩阵>×<模型矩阵>×<原始顶点坐标>

示例程序在着色器中实现了该式。很简单,直接照着该式修改顶点着色器。修改后的LootAtRotatedTriangles程序实现了上述变换,如下图所示。图中白色虚线为旋转前三角形的所在位置,可以看到三角形确实被旋转过了。

模型视图矩阵程序(LookAtRotatedTriangles.js) 

LookAtRotatedTriangles.js与LookAtTriangles.js相比,只有几处小改动:加入了uniform变量u_ModelMatrix;JavaScript中的main()函数将模型矩阵传给该变量。相应的代码如下所示。

首先,顶点着色器中添加了uniform变量u_ModelMatrix(第7行),该变量从JavaScript中接收模型矩阵,以实现等式<视图矩阵>×<模型矩阵>×<原始顶点坐标>。 

JavaScript的main()函数已经有了与视图矩阵相关的代码,只需添加几行计算和传入旋转矩阵的代码,将三角形绕Z轴旋转10度。第53行代码实现了获取u_ModelMatrix变量的存储地址,第64行实现了创建一个新的矩阵对象modelMatrix,调用Matrix.setRotate()将其设为旋转矩阵(第65行),然后传给顶点着色器中的u_ModelMatrix(第69行)。

运行示例程序,顶点坐标依次与旋转矩阵和视图矩阵相乘,最终获得了预期的效果。如上图所示,即先用u_ModelMatrix旋转三角形,再将旋转后的坐标用u_ViewMatrix变换到正确的位置,使其看上去就像是从指定视点处观察一样。

模型视图矩阵

LookAtRotatedTriangle.js中,着色器实现了式(视图矩阵×模型矩阵×原始坐标)。这样,程序对每个顶点都要计算视图矩阵×模型矩阵。如果顶点数量很多,这一步操作就会造成不必要的开销。这是因为,无论对哪个顶点而言,式(视图矩阵×模型矩阵×原始坐标中的两个矩阵相乘的结果都是一样的。所以我们可以在JavaScript中事先把这两个矩阵相乘的结果计算出来,再传给顶点着色器。这两个矩阵相乘得到的结果被称为模型视图矩阵(model view matrix),如下所示:

<模型视图矩阵>=<视图矩阵>×<模型矩阵>

视图矩阵×模型矩阵×原始坐标可以重写为下式

<模型视图矩阵>×<顶点坐标>

新的示例程序LookAtRotatedTriangles_mvMatrix.js按照式<模型视图矩阵>×<顶点坐标>重写了LookAtRotatedTriangles中的代码,如下所示。

顶点着色器中出现了新的uniform变量u_mvMatrix,它参与了对gl_Position的计算(第9行)。顶点着色器执行的流程与最初的LookAtTriangles.js中一样(除了uniform变量的名称)。

在JavaScript代码中,我们分别计算出了视图矩阵viewMatrix和模型矩阵modelMatrix(第59~63行),就像在LookAtTriangle.js中一样。然后,我们调用Matrix4.multiply()方法使这两个矩阵相乘,并将结果赋值给modelviewMatrix(第66行)。注意,我们是在viewMatrix上调用了multiply()方法,并传入modelMatrix为参数,所以这样做的结果实际上就是modelViewMatrix=viewMatrix*modelMatrix。因为在JavaScript中,我们不能像在GLSL ES中那样直接使用*号来进行矩阵相乘,而需要用矩阵库所提供的方法。 

得到了modelViewMatrix后,就将它传给着色器的u_ModelMatrix变量(第69行)。运行程序,效果如下图所示。

最后还需要指出,示例程序显式地把视图矩阵和模型矩阵单独计算出来,再相乘为模型视图矩阵(第59~66行),是为了更好地表达模型视图矩阵的由来。实际上,只需要一行代码就可以计算出模型视图矩阵了:(计算出视图矩阵,再将视图矩阵与模型矩阵(当前只有旋转)相乘)

相关文章:

WebGL 视图矩阵、模型视图矩阵

目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点: 观察目标点: 上方向: 在WebGL中,观察者的默认状态应该是这样的: 视图矩阵程序(LookAtTriangles.js) 实际上&…...

Python 3 – 文件 readline() 方法

Python 3 – 文件 readline() 方法|极客笔记 # 打开文件 file open("example.txt", "r")# 读取文件中的一行数据 line file.readline() while line:# 移除行尾的换行符print(line.strip())# 读取文件中的下一行数据line file.readline()# 关闭文件 file…...

如何在微软Edge浏览器上一键观看高清视频?

编者按:视频是当下最流行的媒体形式之一。但由于视频压缩、网络不稳定等原因,我们常常可以看到互联网上的很多视频其画面质量并不理想,尤其是在浏览器端,这极大地影响了观看体验。不过,近期微软 Edge 浏览器推出了一项…...

Telegram BoT的主流项目盘点

目录 DeFi 类 数据分析类 空投埋伏交易 其他 Telegram Bot赛道的发展趋势预测 Telegram BoT赛道发展较快,具体来看可以分为DeFi 类、数据分析类、空投埋伏交易类以及其他。 DeFi 类 Unibot(交易)、Banana Gun、WagieBot(交…...

PTA 甲级 1044 Shopping in Mars

题目链接 思路&#xff1a;前缀和滑动窗口 #include<bits/stdc.h> #define MAXN 100010 using namespace std; int a[MAXN];int main(){int n,m;cin>>n>>m;//n数量 m金额for(int i1;i<n;i){int t;cin>>t;a[i]a[i-1]t;//前缀和}vector<pair<in…...

Linux学习之MyCat实现分库分表

环境准备 先准备一套MySQL主从服务器&#xff0c;可参考MySQL主从配置配置MyCat服务 资源下载 网盘链接: https://pan.baidu.com/s/1cLTMH_e1-6loc_gF9ZNHTg?pwda63n 提取码: a63n MyCat配置 # 1&#xff09;安装mycat软件 //安装jdk [rootmycat58 upload]# yum -y insta…...

DirectX12(d3d12)初始化

一、前置要求 Windows 10及以上(安装有DirectX12)VisualStudio 2022 二、DirectX12入门 1.引用头文件 #include<Windows.h> #include<d3d12.h> #include<dxgi1_4.h>2.注册窗口类并初始化窗口 这里我们调用Windows API 通过应用程序的句柄来注册一个唯一…...

算法通关村-----回溯模板如何解决排列组合问题

组合总和 问题描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限…...

【1++的C++进阶】之智能指针

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C进阶】 文章目录 一&#xff0c;什么是智能指针二&#xff0c;为什么需要智能指针三&#xff0c;智能指针的发展 一&#xff0c;什么是智能指针 要了解智能指针&#xff0c;我们先要了解RA…...

一百七十九、Linux——Linux报错No package epel-release available

一、目的 在Linux中配置Xmanager服务时&#xff0c;执行脚本时Linux报错No package epel-release available 二、解决措施 &#xff08;一&#xff09;第一步&#xff0c;# wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm &#xff08;二&…...

【AI视野·今日CV 计算机视觉论文速览 第248期】Mon, 18 Sep 2023

AI视野今日CS.CV 计算机视觉论文速览 Mon, 18 Sep 2023 Totally 83 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;Robust e-NeRF,处理高速且大噪声事件相机流的NERF模型。(from NUS新加坡国立) 稀疏噪声事件与稠密事件数据的区别&#xff1a;…...

解决Vue项目中的“Cannot find module ‘vue-template-compiler‘”错误

1. 问题描述 在Vue项目中&#xff0c;当我们使用Vue的单文件组件&#xff08;.vue文件&#xff09;时&#xff0c;有时会遇到以下错误信息&#xff1a; ERROR: Cannot find module vue-template-compiler这个错误通常发生在我们使用Vue的版本不匹配或者缺少必要的依赖模块时。…...

tensorflow基础

windows安装tensorflow anaconda或者pip安装tensorflow&#xff0c;tensorflow只支持win7 64系统&#xff0c;本人使用tensorflow1.5版本&#xff08;pip install tensorflow1.5&#xff09; tensorboard tensorboard只支持chrome浏览器&#xff0c;而且加载过程中可能有一段…...

spring_注解笔记

spring使用注解开发 文章目录 1.前提1 Bean2 属性注入3 衍生的注解4.自动装配5 作用域 1.前提 步骤1&#xff1a; 要使用注解开发&#xff0c;就必须要保证AOP包的导入 步骤2&#xff1a; xml文件添加context约束 步骤3&#xff1a; 配置注解的支持 <context:annotation-…...

c++运算符重载

目录 运算符重载的基本概念 重载加号运算符() 类内实现 类外实现 运算符重载碰上友元函数 可重载和不可重载的运算符 可重载的运算符 不可重载的运算符 重载自加自减运算符(a a) 智能指针 重载等号运算符&#xff08;&#xff09; 重载等于和不等运算符&#xff08…...

vue子组件向父组件传参的方式

在Vue中&#xff0c;子组件向父组件传递参数可以通过自定义事件和props属性来实现。下面是一些关键代码示例&#xff1a; 1. 使用自定义事件&#xff1a; 在子组件中&#xff0c;通过 $emit 方法触发一个自定义事件&#xff0c;并传递参数。 <template><button cli…...

代码随想录Day41| 343. 整数拆分 |

343. 整数拆分 class Solution { public:int integerBreak(int n) {vector<int> f(n1,0);f[2]1;for(int i3;i<n;i){for(int j1;j<i-1;j){f[i]max(f[i],max(f[i-j]*j,(i-j)*j));}}return f[n];} }; 96. 不同的二叉搜索树 class Solution { public:int numTrees(int…...

工厂模式-(简单工厂模式)

首先看一下设计模式的六大原则 设计模式的六大原则 1、开闭原则&#xff08;Open Close Principle&#xff09; 开闭原则就是说对扩展开放&#xff0c;对修改关闭。在程序需要进行拓展的时候&#xff0c;不能去修改原有的代码&#xff0c;实现一个热插拔的效果。所以一句话概…...

V8引擎是如何提升对象属性访问速度的?

JavaScript 中的对象是由一组组属性和值的集合&#xff0c;从 JavaScript 语言的角度来看&#xff0c;JavaScript 对象像一个字典&#xff0c;字符串作为键名&#xff0c;任意对象可以作为键值&#xff0c;可以通过键名读写键值。 然而在 V8 实现对象存储时&#xff0c;并没有…...

彩色相机工作原理——bayer格式理解

早期&#xff0c;图像传感器只能记录光的强弱&#xff0c;无法记录光的颜色&#xff0c;所以只能拍摄黑白照片。 1974年,拜尔提出了bayer阵列&#xff0c;发明了bayer格式图片。不同于高成本的三个图像传感器方案&#xff0c;拜尔提出只用一个图像传感器&#xff0c;在其前面放…...

IDEA中DEBUG技巧

Debug 介绍 Debug 设置 如上图标注 1 所示&#xff0c;表示设置 Debug 连接方式&#xff0c;默认是 Socket。Shared memory 是 Windows 特有的一个属性&#xff0c;一般在 Windows 系统下建议使用此设置&#xff0c;相对于 Socket 会快点。 ## Debug 常用快捷键 Win 快捷键M…...

人工智能训练师

人工智能训练师是一个较新的职业&#xff0c;2020年2月才被正式纳入国家职业分类目录。他们主要负责在人工智能产品使用过程中进行数据库管理、算法参数设置、人机交互设计、性能测试跟踪及其他辅助作业。 这个职业的背景源于AI公司从客户&#xff08;用户&#xff09;那里获取…...

【业务功能118】微服务-springcloud-springboot-Kubernetes集群-k8s集群-KubeSphere-OpenELB部署及应用

OpenELB部署及应用 一、OpenELB介绍 网址&#xff1a; openelb.io OpenELB 是一个开源的云原生负载均衡器实现&#xff0c;可以在基于裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。OpenELB 项目最初由 KubeSphere 社区发…...

Unity中Shader的模板测试

文章目录 前言什么是模板测试1、模板缓冲区2、模板缓冲区中存储的值3、模板测试是什么&#xff08;看完以下流程就能知道模板测试是什么&#xff09;模板测试就是在渲染&#xff0c;后渲染的物体前&#xff0c;与渲染前的模板缓冲区的值进行比较&#xff0c;选出符合条件的部分…...

Scala 高阶:Scala中的模式匹配

一、概述 Scala中的模式匹配&#xff08;case&#xff09;类似于Java中的switch...case&#xff0c;但是Scala的模式匹配功能更为强大。通过模式匹配&#xff0c;可以匹配更复杂的条件和数据结构&#xff0c;包括常量、类型、集合、元组等。而 Java 的 switch 语句只能用于匹配…...

分子生物学——分子机器

分子生物学——分子机器 文章目录 前言一、2016年度诺贝尔化学奖1.1. 介绍1.2. 什么是分子机器&#xff1f;1.3. 分子机器的意义 总结 前言 对于本次搜集分子生物学领域的一个诺贝尔奖的有关内容的作业 参考文献&#xff1a; https://www.cas.cn/zt/sszt/2016nobelprize/hxj/2…...

【简历优化】这套「实习、初级、中级」测试工程师求职简历模板,建议收藏。

历时2年&#xff0c;7000粉丝问答&#xff0c;帮助上百位“刚培训毕业”、“1~3年经验”的软件测试伙伴&#xff0c;成功入职&#xff01; 我将这些问题内容&#xff0c;会持续更新记录在 「软件测试」求职指南 专栏。 求职简历中的误区 对于简历应该具备哪些模块&#xff0c…...

vue中展示json数据的方法

推荐插件&#xff1a;bin-code-editor (gitee.io) bug-1:编辑器无法显示数据 原因&#xff1a;组件层级套用太深&#xff0c;导致无法显示数据 解决办法&#xff1a;减少在孙子及后代组件中使用插件。...

【SG滤波】三阶滤波、五阶滤波、七阶滤波(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

2013 ~【VUE+ ElementUI】——【上传、下载】进度计算

【VUE ElementUI】——【上传、下载】进度计算 上传&#xff1a;FormData方式上传&#xff0c;监听 onUploadProgress下载&#xff1a;blob文件流下载&#xff0c;监听 onDownloadProgress 上传&#xff1a;FormData方式上传&#xff0c;监听 onUploadProgress <el-upload:…...

蜂蜜网站建设/googleseo推广

win10控制台打不开提示管理员已阻止mmc.exe怎么办&#xff1f;最近有win10用户在打开控制台的时候发现打不开了&#xff0c;提示管理员已阻止mmc.exe。这是怎么回事呢&#xff1f;我们该如何解决控制台打不开提示管理员已阻止mmc.exe的问题呢&#xff1f;首先我们先了解一下mmc…...

福建漳州网站建设费用/什么是关键词搜索

1. where条件中有or,除非or的所有字段都有索引&#xff0c;只要有一个没有索引&#xff0c;就不走索引上面name和id都有索引上面money没有索引2.对于多列索引&#xff0c;第一列会使用索引&#xff0c;单独其他列不会&#xff0c;用or连接多列不会使用索引&#xff0c;用and会使…...

网页设计与网站建设奥鹏考试答案/站长收录平台

为什么80%的码农都做不了架构师&#xff1f;>>> 各位ccflow 爱好者: 最近推出一些ccflow5的视频教程&#xff0c;如下: http://video.sina.com.cn/v/b/102317000-1618288504.html 驰骋工作流引擎-同表单分合流设计过程 http://video.sina.com.cn/v/b/102314852-…...

如何在网站后台做超链接到文档/女教师遭网课入侵直播录屏曝光se

《三体》的第三体一个宇宙的时代&#xff08;不以年计&#xff09;&#xff0c;书中的故事主角永存&#xff0c;其他所有被时间洗涮着。结局&#xff1a;所有文明生存的空间被自己玩完&#xff0c;有文明向宇宙中所有 100 多万个文明发出了信息。但一切已成定局。故事小结&…...

做任务领游戏的网站/百度股市行情上证指数

1.环境描述Centos 72.安装步骤通过命令yum install docker安装等待下载安装…,出现下图&#xff0c;按y继续继续等待…出现下图按y继续再继续等待…知道出现上图表示安装完毕3.测试安装是否成功执行命令docker后&#xff0c;如果与下图内容一致 则表示成功4.启动docker我们在执…...

石岩网站建设 0755/seo关键词优化培训班

首先要在windows下解压一个windows版本的hadoop 然后在配置他的环境变量&#xff0c;同时要把hadoop的share目录下的hadoop下的相关jar包拷贝到esclipe 然后Build Path 下面上代码 import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException…...