C++和OpenGL实现3D游戏编程【连载14】——VBO、VAO和EBO应用

news2024/11/25 22:58:29

🔥C++和OpenGL实现3D游戏编程【目录】

1、本节实现的内容

我们从一开始学OpenGL到现在,OpenGL的图形绘图必须在glBegin()和glEnd()函数之间完成,在此基础之上,才能进行后续操作功能。但是我们今天要讨论一下OpenGL图形绘制的模式,从之前的立即渲染模式,开始转向核心模式,从而大幅提升显示性能。下图就是通过VBO、VAO和EBO应用画出的一个矩形,矩形虽然简单,但它的意义却不凡。

在这里插入图片描述

2、立即渲染模式

OpenGL的绘图的函数模式很多,比如绘制点的模式GL_POINTS、直线GL_LINES 、三角形GL_TRAINGLES、四边形GL_QUADS等等。OpenGL的绘图必须在glBegin()和glEnd()函数之间完成,这种方式使我们简单、直观的进行了基本几何绘图函数。像下面这个绘制三角形的操作:

	//绘画一个三角形

	glBegin( GL_TRIANGLES );

	glVertex3f(-1.0f,-0.5f,-2.0f);

	glVertex3f( 1.0f,-0.5f,-2.0f);

	glVertex3f( 0.0f,0.5f,-2.0f);

	glEnd();

客观的说,这种绘图方式最主要的特点就是看起来比较简单,容易理解,就是我们所说的立即显示模式。但是这种方式也有缺点,就是画图形的显示效率较低。原因是在于glVertex函数每次调用只把一个顶点(坐标数据)从客户端(CPU或内存)传输到显示处理设备(GPU),而这个传输的过程相对于GPU处理数据的过程是很慢的。如果显示的图形数量不多的情况下,不会出现问题,但后期随着绘制图形的越来越复杂,位置的图形数量越来越多,需要使用的glVertex函数的调用次数就会越来越多,这将直接导致传统的立即显示模式执行效率有所下降。

3、什么是GPU和显存

首先,我们需要了解一下GPU和显存的基本概念。GPU全称图形处理器(Graphics Processing Unit),是一种专门用于处理图像和视频信息的微处理器。它拥有强大的并行处理能力,可以高效地执行复杂的图形渲染任务,GPU是显卡的核心部件。显存,也就是显卡里的内存。显卡的GPU访问显存,比访问内存(CPU里的内存区域)要快很多。而且显卡做渲染运算,一般都是访问显存的数据,再对数据进行运算,并把运算结果保存在显存中。所以一般,我们为了提示游戏性能,需要先把数据先从内存一次性传输到显存中去,后期由GPU对显存中数据进行显示和渲染。

4、核心模式下图形渲染方式

了解以上铺垫知识了以后,我们就明白此后我们将尽可能少在使用立即显示模式去显示图形。当我们使用OpenGL绘制图形时,需要将顶点的位置、颜色等信息传递给显卡,让显卡进行绘制,为了提高效率,我们需要把数据先从内存一次性传输到显存中去,后期由GPU对显存中数据进行显示和渲染。该操作主要包括以下内容:

  • VBO(Vertex Buffer Object)是用来存储这些顶点数据的特殊缓冲区,可以将数据保存在显卡中,避免频繁地从CPU传输数 据到显卡,提高绘制效率。

  • VAO(Vertex Array Object)则是用来管理这些顶点数据的设置的。绘制一个图形通常需要多个顶点属性(比如位置、颜色等),VAO帮助我们预先指定这些属性在VBO中的排列方式,避免在每次绘制时重新设置属性,简化绘制代码。

  • EBO(Element Buffer Object)是用来存储图元的索引数据的缓冲区,比如三角形的三个顶点索引。它可以帮助我们避免重复存储顶点数据,只需存储少量的索引数据就可以描述复杂的图形,提高绘制效率。

在这里插入图片描述

综合来说,VBO、VAO和EBO是帮助我们优化OpenGL绘制图形的工具。它们的组合可以让我们更高效地绘制图形,让图形的渲染速度更快,性能更好。也就是说从现在开始,我们开始去了解GPU的操作相关知识,这才是游戏设计的灵魂所在。

5、VBO(Vertex Buffer Object)顶点缓冲对象

VBO(Vertex Buffer Object)顶点缓冲对象,是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法向量,顶点颜色数据等。在渲染时,可以直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。所以可以理解为VBO就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个VBO,每个VBO在OpenGL中有它的唯一标识ID,这个ID对应着具体的VBO的显存地址,通过这个ID可以对特定的VBO内的数据进行存取操作。比如我们有以下三个顶点数据信息:

	//自定义顶点

	float vertices[] = {

		-0.5f, -0.5f, 0.0f,
    
		0.5f, -0.5f, 0.0f,
     
		0.0f,  0.5f, 0.0f
		
	};

以上三个顶点我们是通过数组保持的,后期发送到顶点缓冲区,也会是连续顶点的存储模式,每一个点(VERTEX)的位置坐标数据包含x,y,z三个分量,每个点位置信息存储占用为12个字节。这些点位置信息之间没有空隙(或其他值),在数组中紧密排列。如下图:
在这里插入图片描述

当然,数据信息也可能包含了颜色和纹理坐标信息:

在这里插入图片描述

顶点缓冲对象(VBO)就像OpenGL中的其它对象一样,这个缓冲有一个独一无二的ID,所以我们可以使用glGenBuffers函数和一个缓冲ID生成一个VBO对象。随后glBufferData是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数。它的第一个参数是目标缓冲的类型:当前绑定到GL_ARRAY_BUFFER目标上的顶点缓冲对象。第二个参数指定传输数据的大小(以字节为单位),用一个简单的sizeof计算出顶点数据大小就行。第三个参数是我们希望发送的实际数据。

    //生成VBO对象,缓冲ID为VBO
    
    unsigned int VBO;
    
	//使用元素缓冲对象EBO

	glGenBuffers(1, &EBO); 

	//第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	
	//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多
	
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//设置完属性,解绑VBO	
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);

VBO是CPU和GPU传递信息的桥梁,我们把数据存入VBO是在CPU上操作,VBO会自动将数据送至GPU。送至GPU不需要任何人为操作。关于VBO另外补充解释:使用VBO管理内存(GPU上储存顶点数据),使用VBO好处就是将内存一次性发送大批数据到显卡,而不是每次发送一个顶点数据。从CPU把这些数据发送到显卡相对较慢,所以只要可能就尝试尽量一次性尽可能多的数据。发送到显卡的内存后,顶点着色器几乎能立即访问顶点,过程比较快。

Buffer Object,就是由OpenGL维护的一块显存区域。比如说在一块显存为2G的显卡里,分配了128K大小的内存区域给OpenGL使用,这个128K大小的内存区域,就叫一个Buffer Object。

我们已经把顶点数据发送给了GPU,但OpenGL还不知道它该如何解释内存中的顶点数据。也就是说,GPU内的这块显存区域里是紧密连续的一个个数据,OpenGL并不知道从哪里到哪里是一个顶点的数据,从哪里到哪里是这个顶点的RGB值(如果有的话),因此要显示这些顶点,我们还需要顶点数组对象(Vertex Array Object, VAO)配合使用。同时,我们也该告诉OpenGL,该如何将顶点数据链接到顶点着色器的属性上,着色器部分我们下节课在详细描述。

VBO是顶点缓冲对象,是CPU和GPU中间的桥梁,开发者只需要将数据存入VBO中,VBO自动将数据送入GPU中。而VBO传输的只是一堆数字,GPU怎么解释这些顶点数据,就需要VAO来解释。

6、VAO(Vertex Array Object)顶点数组对象

VAO(Vertex Array Object)顶点数组对象,可以像顶点缓冲对象那样被绑定,任何随后的顶点属性调用都会储存在这个VAO中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,刚刚设置的所有状态(顶点坐标属性、颜色属性、纹理坐标属性等)都将同时绑定并存储在一个VAO中,之后再绘制物体的时候只需要绑定相应的VAO就行了。这使在不同顶点数据和属性配置之间切换变得非常简单,只需要绑定不同的VAO就行了。

	//生成VAO
	
	glGenVertexArrays(1, &VAO);
	
	//绑定VAO,从绑定之后起,我们应该绑定和配置对应的VBO和属性指针,之后解绑VAO,供之后使用
	
    glBindVertexArray(VAO);

	//第一个参数GLsizei是要生成的缓冲对象的数量,第二个GLuint是要输入用来存储缓冲对象名称的数组

	glGenBuffers(1, &VBO);
      
 	//绑定到目标对象,VBO变成了一个顶点缓冲类型,第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
        
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多

	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	
	//启用顶点属性layout(location = 0),顶点属性默认是禁用的。供着色器使用,着色器操作下节课详细介绍
	
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	 
	//设置完属性,解绑VBO	
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	
  	//配置完VBO及其属性,解绑VAO,后期显示图元的时候再次绑定VAO  
  		
  	glBindVertexArray(0);

在 OpenGL 中,使用顶点数组对象(VAO)可以方便地管理顶点属性的状态。绑定 VAO、设置顶点属性、然后解绑 VAO 的顺序是为了确保顶点属性的设置被正确地记录在 VAO 中,从而简化渲染代码并提高效率。OpenGL的核心模式要求我们使用VAO,所以它知道该如何处理我们的顶点输入。以下就是通过VAO显示对应VBO中三角形的方法:

         //绑定VAO
         
         glBindVertexArray(VAO);
         
         //从VAO中读取数据画出三角形
         
         glDrawArrays(GL_TRIANGLES, 0, 3);
         
         //使用完毕后解绑VAO
         
         glBindVertexArray(0);

如果你像我这样成功绘制出了这个三角形或矩形,那么恭喜你,你成功地通过了现代OpenGL入门的拦路虎之一,绘制你自己的第一个三角形或矩形,因为这些操作确实很抽象。当然我们这里暂时没有使用着色器,下节课我们会详细介绍着色器内容。如果我们绑定VAO失败,OpenGL会拒绝绘制任何东西。

7、EBO(Element Buffer Object)元素缓冲对象

EBO(Element Buffer Object)元素缓冲对象,也叫索引缓冲对象(Index Buffer Object,IBO)。要解释元素缓冲对象的工作方式最好还是举个例子:假设我们不再绘制一个三角形而是绘制一个矩形。我们可以绘制两个三角形来组成一个矩形(OpenGL主要处理三角形)。这会生成下面的顶点的集合:

GLfloat vertices[] = {

    // 第一个三角形
    
    0.5f, 0.5f, 0.0f,   // 右上角
    
    0.5f, -0.5f, 0.0f,  // 右下角
    
    -0.5f, 0.5f, 0.0f,  // 左上角
    
    // 第二个三角形
    
    0.5f, -0.5f, 0.0f,  // 右下角
    
    -0.5f, -0.5f, 0.0f, // 左下角
    
    -0.5f, 0.5f, 0.0f   // 左上角
    
};

可以看到,有几个顶点叠加了。我们指定了右下角和左上角两次!一个矩形只有4个点而不是6个顶点,这样就产生50%的额外开销。当我们有包括上千个三角形的模型之后这个问题会更糟糕,这会产生一大堆浪费。更好的解决方案是只储存不同的顶点,并设定绘制这些顶点的顺序。这样子我们只要储存4个顶点就能绘制矩形了,之后只要指定绘制的顺序就行了。首先,我们先要定义(不重复的)顶点,和绘制出矩形所需的索引:

GLfloat vertices[] = {

    0.5f, 0.5f, 0.0f,   // 右上角
    
    0.5f, -0.5f, 0.0f,  // 右下角
    
    -0.5f, -0.5f, 0.0f, // 左下角
    
    -0.5f, 0.5f, 0.0f   // 左上角
    
};

GLuint indices[] = { 

    0, 1, 3, // 第一个三角形,注意索引从0开始
    
    1, 2, 3  // 第二个三角形,注意索引从0开始
    
};

创建元素缓冲对象与VBO类似,我们先绑定EBO然后用glBufferData把索引复制到缓冲里。同样,EBO的使用和VBO类似,我们会把这些EBO的相关操作放在VAO绑定和VAO解绑操作调用之间,只不过这次我们把缓冲的类型由VBO的GL_ARRAY_BUFFER改变成为GL_ELEMENT_ARRAY_BUFFER。

	//使用元素缓冲对象EBO

	glGenBuffers(1, &EBO); 

	//第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	
	//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多
	
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

最后一件要做的事是用glDrawElements来替换glDrawArrays函数,表示我们要从索引缓冲区渲染三角形。使用glDrawElements时,我们会使用当前绑定的索引缓冲对象中的索引进行绘制:

    //绑定VAO
         
    glBindVertexArray(VAO);
    
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

	glDrawElements(GL_TRIANGLES,sizeof(indices),GL_UNSIGNED_INT,0);
	
    //使用完毕后解绑VAO
         
    glBindVertexArray(0);

这部分操作很难,因为在绘制第一个三角形之前你需要了解很多知识。幸运的是我们现在已经越过了这个障碍,接下来的教程会比较容易理解一些。

8、绑定和解绑顺序

我们通常绑定和解绑有一定的顺序,创建顺序:VAO->VBO->EBO, 解绑顺序:VAO->VBO->EBO。需要注意的是,当VAO处于活动状态时,不能解绑EBO, 因为绑定的元素缓冲区对象存储在VAO中。其实VAO每次使用都需要调用glBindVertexArray,它会直接解绑旧的对象并且绑定一个新的,因此通常情况下,我们不需要通过调用 glBindVertexArray(0) 来解绑VAO,当然VBO也是这样。所以在使用中,无需过度在意是否解绑了VAO和VBO,通常是不需要解绑的。

9、核心模式渲染实例

我们以上讲解了和核心模式下VBO、VAO和EBO的相关知识,所举得实例相对较为分散,那么我们现在就接合以上三部分知识,完成个简单的综合实例,生成一个矩形,直观的感受一下核心模式渲染实例。

      //自定义VAO对象,缓冲ID为VAO,当然这里VAO就是一个变量名,名字可以自己随便起,比如VaoExample等等
      
      unsigned int VAO;
      
      //自定义VBO对象,缓冲ID为VBO
      
      unsigned int VBO;
      
      //自定义VBO对象,缓冲ID为VBO
      
      unsigned int EBO;

自定义顶点数据

	//定义顶点对象
	
	float vertices[] = {
			
	//位置信息					//颜色信息	
	
	-5.0f, 0.0f, 6.0f,		1.0f,0.0f,0.0f,		
		
	5.0f, 0.0f, 6.0f,		0.0f,1.0f,0.0f,	
	
	5.0f, 10.0f, 6.0f,		0.0f,0.0f,1.0f,		
		
	-5.0f, 10.0f, 6.0f,		1.0f,1.0f,1.0f	
			
	};
	
	  unsigned int indices[]={
	  
		 0, 1, 3, // 第一个三角形,注意索引从0开始
    
   		 1, 2, 3  // 第二个三角形,注意索引从0开始
		
	  };

生成并绑定VAO

	//生成VAO
	
	glGenVertexArrays(1, &VAO);
	
	//绑定VAO,从绑定之后起,我们应该绑定和配置对应的VBO和属性指针,之后解绑VAO,供之后使用
	
    glBindVertexArray(VAO);

生成并绑定VBO

	//第一个参数是要生成的缓冲对象的数量,第二个GLuint是要输入用来存储缓冲对象名称的数组

	glGenBuffers(1, &VBO);
      
 	//绑定到目标对象,第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
        
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多

	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

生成并绑定EBO

	//使用元素缓冲对象EBO

	glGenBuffers(1, &EBO); 

	//第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	
	//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多
	
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

这里是着色器相关设置,下节课详细讲解着色器

	//启用顶点属性layout(location = 0),顶点属性默认是禁用的。供着色器使用,下节课详细讲解着色器
	
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);

	//启用顶点属性layout(location = 1),顶点属性默认是禁用的。供着色器使用,下节课详细讲解着色器
	
	glEnableVertexAttribArray(1);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));

使用完毕后解绑相关对象

  	//配置完VBO及其属性后,解绑VAO,后期显示图元的时候再次绑定VAO  
  		
  	glBindVertexArray(0);
  	
	//设置完属性,解绑VBO	
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);

显示图像,需要先绑定VAO

	//使用着色器,下节课详细介绍着色器

	//glUseProgram(shaderProgram);
	
	//绑定VAO

    glBindVertexArray(VAO); 

	//不使用EBO方式绘制三角形,起始索引0,绘制顶点数量3

	//glDrawArrays(GL_TRIANGLES,0,3);

    //使用EBO方式绘制三角形,共绘制6个顶点

	glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);

	//解绑VAO

    glBindVertexArray(0); 
    
	//不在使用着色器,下节课详细介绍着色器

	//glUseProgram(0);

通过以上过程,我们应该能够在三维空间中显示一个四边形,但是你会发现它并没有颜色,主要时由于本节课为了简化,我们暂未使用着色器去处理颜色信息,待下节课结合着色器进行学习后,就能显示四边形正常的颜色了。

在这里插入图片描述

10、总结

在介绍VBO、VAO和EBO三个要素时,大家有可能觉得很迷茫,很多教程中并没有说明为什么要由立即渲染模式转变为核心模式,搞不明白我们为什么原来用的好好的显示函数,我们为什么突然又要讲这VBO、VAO和EBO这三个全新的东西?本节课我就接合学习过程中的一些感触,简单解释了一下这个问题,希望能对您有所帮助。但也值得庆幸的是,特别是我们在随后的游戏设计时,已经开始慢慢从CPU接触到了GPU,游戏的意义从这里才开了一个新的纪元。而且在我们下节课讲到着色器时,会更加体会到OpenGL3.2之后3D世界重大变革的方向,开发者在VBO、VAO和EBO结合着色器的核心模式下进行开发,程序设计自由度更高,游戏设计的魅力又增加了许多。

在这里插入图片描述

【上一节】:🔥C++和OpenGL实现3D游戏编程【连载13】——多重纹理混合详解

【下一节】:🔥C++和OpenGL实现3D游戏编程【连载14】——着色器初步

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

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

相关文章

前端父子传递属性值

1. Vue3.4.X之前  2. Vue3.4.X之后版本 defineModel 父页面  子页面   

Python | Leetcode Python题解之第463题岛屿的周长

题目: 题解: class Solution:def islandPerimeter(self, grid: List[List[int]]) -> int:rowlen(grid)collen(grid[0])nums0c0gridgrid[[0]*col]for i in range(row):grid[i].append(0)for j in range(col):if grid[i][j]1:nums1if grid[i][j]1 and …

跨境独立站还能做多久?谈谈独立站的长期价值

这几年,品牌出海与跨境独立站成了商业圈子的热门话题。伴随而来的则是日益激烈的市场竞争,不少新入局的卖家纷纷抱怨:“现在做独立站已经赚不到钱了!”都发出了灵魂拷问,**跨境独立站还能做几年?**跨境电商…

【hot100-java】合并 K 个升序链表

链表篇 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ class Solu…

基于Python的在线音乐平台

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

qemu启动busybox虚拟机网络连接配置

一、busybox文件系统网络问题 由于根文件是用busybox构建,所以很多配置文件是没有的,包括部分网络的默认设置。启动虚拟机后只能使用ip命令和ifconfig命令查看网络状态。 二、开启qemu网络支持 想要使虚拟机上网,最简单的方式可以使用 -netde…

javaweb 文件存储

文件上传,是指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。 文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。 上传文件的原始form表单,要求表单必须具备以下三点…

双十一买些提高幸福感的生活单品!五款精选好物推荐~

双十一购物狂欢即将来临,这是一年一度的购物盛宴,家电和数码产品通常会在这个时期提供诱人的折扣。但品牌众多,每款产品又各有千秋,让人难以抉择。今天,我将分享一些在双十一期间值得考虑的高品质好物,让我…

【视频笔记】408新增知识点信号——里昂视频

文章目录 **2.信号****3.信号的实现**4.信号的处理**①忽略信号****②执行信号的默认操作****③捕获井处理信号**几个Linux支持的典型信号: **5.信号的产生**① **通过终端按键(键盘)产生信号**例如,CtrlC发送2号信号SIGINT、Ctrl\发送3号信号SIGQUIT② …

Matlab实现海洋捕食者优化算法优化回声状态网络模型 (MPA-ESN)(附源码)

目录 1.内容介绍 2部分代码 3.实验结果 4.内容获取 1内容介绍 海洋捕食者优化算法(Marine Predators Algorithm, MPA)是一种基于海洋生物捕食行为的新型群体智能优化算法。MPA通过模拟海洋捕食者如鲨鱼、海豚等在寻找猎物时的追踪、包围和攻击行为&…

双十一购买清单,应该如何选购宠物空气净化器,有哪几款推荐

作为一个宠物博主,每天都有人来问我家里养了猫应该怎么样才能清理浮毛,到底有哪些值得推荐。 这我可是有话说,当初就是心血来潮养了两只长毛猫,直到现在都还一直在清理猫咪掉毛的问题。猫咪掉的毛,不仅是会掉在沙发上…

EmEditor传奇脚本编辑器

主程序:EmEditor.exe 目前已有功能 可以自己指定一个快捷键 实现以下功能(默认快捷键为:F1) 以下全功能 都是鼠标所在行 按快捷键 (默认快捷键:F1) 1.在Merchant.txt中 一键打开NPC 没有…

11.Lab Ten —— mmap

内存映射文件(Memory-Mapped File)是一种将文件内容映射到进程的虚拟地址空间的技术,使得文件的内容可以像内存一样被访问。 通过内存映射文件,可以高效地访问和操作文件内容 首先切换到mmap分支 git checkout mmap make clean…

【机器学习】随机森林算法(看我以弱博强)

目录 算法引入: 算法介绍: 1. 集成学习: 2. 训练过程: 3. 分类和回归: 算法优点: 算法缺点: 算法实现: 1. 数据准备 2. 划分数据集 3. 创建随机森林模型 4. 训练模型 5…

Kubesphere4.1版本创建应用Mysql并实现外网访问

目前Kubesphere4.1版本可查创建应用资料较少,特此记录作为参考。 目标 使用Kubesphere4.1完成Mysql服务部署并实现外网访问。 具体流程如下: 1.创建企业空间 2.创建项目 3.创建应用仓库 4.创建应用(mysql) 5.配置外网访…

抖去推--短视频矩阵系统源码对外资料包

#短视频矩阵系统源码# #短视频矩阵系统源码开发# #短视频矩阵系统源码打包# 一、短视频矩阵系统源码安装 安装环境 短视频矩阵系统源码需要以下环境: PHP 7.0 及以上 MySQL 5.5 及以上 Nginx / Apache Redis FFMpeg 下载源码 从官网下载最新版本的短视频矩阵系统…

浅谈云原生--微服务、CICD、Serverless、服务网格

往期推荐 浅学React和JSX-CSDN博客 一文搞懂大数据流式计算引擎Flink【万字详解,史上最全】-CSDN博客 一文入门大数据准流式计算引擎Spark【万字详解,全网最新】_大数据 spark-CSDN博客 目录 1. 云原生概念和特点 2. 常见云模式 3. 云对外提供服务的…

【linux】麒麟v10安装prometheus监控(ARM架构)

Prometheus介绍 Prometheus 是一个开源的系统监控和警报工具包,最初由 SoundCloud 开发,现在是一个独立的开源项目,并且是云原生计算基金会(CNCF)的一部分。Prometheus 以其强大的数据模型和灵活的查询语言&#xff0…

线下餐厅自主点餐或外卖配送小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 线下餐厅自主点餐或外卖配送小程序源码系统是一款专为餐饮行业打造的智能化解决方案。它融合了自主点餐、外卖配送、订单管理、数据分析等多种功能,为餐厅提供了一站式的服务平台。通过该系统,餐厅可以实现线上线下一体化运营,提高工…