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

OpenGL进阶 | 绘制一个三角形

一、准备绘图数据

  • VBO(Vertex Buffer Object)

        在opengl中,所有的数据都要放在显存中,通过VBO(Vertex Buffer Object)可将CPU数据传到GPU。

        VBO(Vertex Buffer Object)是OpenGL中的一种机制,用于将顶点数据存储在显存中,以便GPU可以快速访问和处理。VBO是一种缓冲对象,类似于CPU中的数组或列表,可以用来存储顶点的位置、颜色、纹理坐标等属性。使用VBO可以避免每次渲染时都需要从CPU到GPU之间复制顶点数据的过程,从而提高了渲染的效率。

GLuint vbo;
void Init()
{float data[] = {-0.2f,-0.2f,-0.6f,1.0f,0.2f,-0.2f,-0.6f,1.0f,-0.2f,0.2f,-0.6f,1.0f};glGenBuffers(1, &vbo);                                                   //需要1个VBO,把vbo写入到显卡进去,供后续操作glBindBuffer(GL_ARRAY_BUFFER, vbo);                                      //把vbo设置到卡槽上//glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12, nullptr,GL_STATIC_DRAW);//只在GPU上开辟内存不传数据glBufferData(GL_ARRAY_BUFFER,sizeof(float)*12,data,GL_STATIC_DRAW);      //将数据从cpu传到Gpu,此后data数据可删除。glBindBuffer(GL_ARRAY_BUFFER, 0);                                        //卡槽重新绑定,防止误操作
}

二、编写Shader

1.顶点着色器

        vertex shader,test.vs文件如下:

attribute vec4 position;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;
void main()
{gl_Position=ProjectionMatrix*ViewMatrix*ModelMatrix*position;
}
  •  uniform和attribute

在OpenGL中,uniform和attribute是用于在着色器程序中传递数据的两种不同类型。

  1. Uniform变量: Uniform变量是一种全局变量,用于在不同的着色器阶段之间传递数据。它们在着色器程序中的任何地方都可以访问,不受顶点或片段的限制。Uniform变量通常用于传递全局数据,例如变换矩阵、光照参数、纹理等。在程序中,你可以使用glGetUniformLocation函数获取Uniform变量的位置(或插槽),然后使用glUniform函数将值传递给Uniform变量。

  2. Attribute变量: Attribute变量是一种顶点属性,用于在顶点着色器中接收每个顶点的输入数据。它们通常用于表示顶点的位置、颜色、法线等属性。Attribute变量只能在顶点着色器中使用,并且每个顶点都会有对应的属性值。在程序中,你可以使用glGetAttribLocation函数获取Attribute变量的位置(或插槽),然后使用glVertexAttribPointer函数设置属性数据的格式和位置。

        关于插槽(location)的分配,Uniform变量和Attribute变量都是从0开始分配的。可以使用glGetUniformLocation和glGetAttribLocation函数获取它们在着色器程序中的位置(或插槽)值。对于Uniform变量,可以使用glUniform函数将值传递给指定位置的Uniform变量。对于Attribute变量,可以使用glVertexAttribPointer函数将属性数据绑定到指定位置的Attribute变量。

        需要注意的是,Uniform变量和Attribute变量在不同的着色器阶段之间传递数据的方式和使用方法是不同的。Uniform变量用于在整个着色器程序中传递全局数据,而Attribute变量用于在顶点着色器中接收每个顶点的属性数据。

2.片段着色器

        fragment shader,test.fs文件如下:

#ifdef GL_ES
precision mediump float;
#endif
void main()
{gl_FragColor=vec4(1.0,1.0,1.0,1.0);
}

三、编译Shader

1.相关函数

  • glCreateShader

GLuint glCreateShader(GLenum shaderType);

        shaderType指示要创建的着色器的类型,支持两种类型的着色器:

  1.  GL_VERTEX_SHADER类型的着色器是一个用于在可编程顶点处理器上运行的着色器。
  2.  GL_FRAGMENT_SHADER类型的着色器是一个着色器,旨在在可编程片段处理器上运行。

        glCreateShader创建一个空的着色器对象,并返回一个可以引用的非零值(Shader ID)。着色器对象用于维护定义着色器的源代码字符串。

  • glShaderSource

        glShaderSource是OpenGL中用于设置着色器源代码的函数。它的作用是将字符串形式的着色器源代码加载到指定的着色器对象中,以便后续编译和链接。具体来说,glShaderSource函数有四个参数:

void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
  1. shader:要设置源代码的着色器对象的ID。
  2. count:要设置的源代码字符串数量。
  3. string:源代码字符串数组的指针。
  4. length:源代码字符串数组中每个字符串的长度,如果为NULL,则默认使用字符串的长度。
  • glCompileShader

        glCompileShader是OpenGL中用于编译着色器对象的函数。它的作用是将glShaderSource函数加载的着色器源代码编译成可执行的着色器程序,供OpenGL渲染时使用。

具体来说,glCompileShader函数有一个参数:

void glCompileShader(GLuint shader);
  1. shader:要编译的着色器对象的ID。
  • glGetShaderiv

            glGetShaderiv是OpenGL中获取着色器对象参数的函数之一,它的作用是获取指定着色器对象的特定参数信息,例如编译状态、参数个数、参数类型等等。具体来说,glGetShaderiv函数有三个参数:

void glGetShaderiv(GLuint shader, GLenum pname, GLint *params);
  1. shader:要查询的着色器对象的ID。

  2. pname:要查询的参数名称,可选值包括:

    • GL_SHADER_TYPE:着色器类型,取值为GL_VERTEX_SHADER或GL_FRAGMENT_SHADER。
    • GL_DELETE_STATUS:着色器是否已被标记为删除。
    • GL_COMPILE_STATUS:着色器编译状态,取值为GL_TRUE或GL_FALSE。
    • GL_INFO_LOG_LENGTH:着色器信息日志的长度,以字符数为单位。
    • GL_SHADER_SOURCE_LENGTH:着色器源代码的长度,以字符数为单位。
    • GL_NUM_SHADER_BINARY_FORMATS:支持的着色器二进制格式数量。
    • GL_SHADER_BINARY_FORMATS:支持的着色器二进制格式列表。
    • 其他参数,例如GL_SHADER_IDENTITY_MATRIX等等。
  3. params:指向存储返回参数值的变量的指针。

  • glDeleteShader

        glDeleteShader是OpenGL中删除着色器对象的函数之一。它的作用是删除已经创建的着色器对象,释放显存中的资源。具体来说,glDeleteShader函数有一个参数:

void glDeleteShader(GLuint shader);
  1. shader:要删除的着色器对象的ID。

        需要注意的是,如果着色器对象已经被附加到程序对象中,那么在程序对象链接之前无法删除着色器对象。因此,通常建议在使用完着色器对象后立即删除它,以免占用过多的显存资源。

2.举个例子

GLuint CompileShader(GLenum shaderType, const char* shaderCode)
{GLuint shader = glCreateShader(shaderType);glShaderSource(shader, 1, &shaderCode, nullptr);glCompileShader(shader);GLint compileResult = GL_TRUE;glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);if (compileResult == GL_FALSE) {char szLog[1024] = { 0 };GLsizei logLen = 0;glGetShaderInfoLog(shader, 1024, &logLen, szLog);printf("Compile Shader fail error log : %s \nshader code :\n%s\n", szLog, shaderCode);glDeleteShader(shader);shader = 0;}return shader;
}

四、链接成程序

1.相关函数

  • glCreateProgram

        glCreateProgram是OpenGL中创建着色器程序对象的函数之一。它的作用是创建一个着色器程序对象并返回其ID,用于管理多个着色器对象的链接过程。具体来说,glCreateProgram函数没有参数,只返回一个GLuint类型的着色器程序对象ID:

GLuint glCreateProgram(void);
  • glAttachShader

        glAttachShader是OpenGL中将着色器对象附加到程序对象的函数之一。它的作用是将一个或多个着色器对象附加到一个程序对象上,为后续的链接操作做准备。具体来说,glAttachShader函数有两个参数:

void glAttachShader(GLuint program, GLuint shader);
  1. program:要附加到的程序对象的ID。
  2. shader:要附加的着色器对象的ID。
  • glLinkProgram

        glLinkProgram是OpenGL中链接着色器程序的函数之一,用于将一个程序对象中所有附加的着色器对象链接为一个可执行程序。在链接过程中,OpenGL会将不同着色器之间的变量名和类型进行匹配和连接,最终生成一个可供GPU执行的着色器程序。具体来说,glLinkProgram函数有一个参数:

void glLinkProgram(GLuint program);
  1. program:要链接的程序对象的ID。

        需要注意的是,glLinkProgram函数链接完成后会将链接日志存储在程序对象中,我们可以通过调用glGetProgramiv函数查询链接状态,或者通过调用glGetProgramInfoLog函数获取链接日志。另外,如果链接失败,程序对象的状态将会被标记为链接失败,并且该程序对象无法使用。

  • glDetachShader

        glDetachShader是OpenGL中将着色器对象从程序对象中分离的函数之一。它的作用是将一个着色器对象从一个程序对象中分离,使该着色器对象可以在其他程序对象中使用。具体来说,glDetachShader函数有两个参数:

void glDetachShader(GLuint program, GLuint shader);
  1. program:要分离着色器对象的程序对象的ID。
  2. shader:要分离的着色器对象的ID。
  • glGetProgramiv

        glGetProgramiv是OpenGL中获取着色器程序对象参数的函数之一。它的作用是获取指定着色器程序对象的特定参数信息,例如链接状态、参数个数、参数类型等等。具体来说,glGetProgramiv 函数有三个参数:

void glGetProgramiv(GLuint program, GLenum pname, GLint *params);
  1. program:要查询的着色器程序对象的ID。

  2. pname:要查询的参数名称,可选值包括:

    1. GL_DELETE_STATUS:程序是否已被标记为删除。
    2. GL_LINK_STATUS:程序链接状态,取值为GL_TRUE或GL_FALSE。
    3. GL_VALIDATE_STATUS:程序验证状态,取值为GL_TRUE或GL_FALSE。
    4. GL_INFO_LOG_LENGTH:链接或验证日志的长度,以字符数为单位。
    5. GL_ATTACHED_SHADERS:附加的着色器对象数量。
    6. GL_ACTIVE_ATTRIBUTES:激活的顶点属性数量。
    7. GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:激活的顶点属性名称的最大长度。
    8. GL_ACTIVE_UNIFORMS:激活的Uniform变量数量。
    9. GL_ACTIVE_UNIFORM_MAX_LENGTH:激活的Uniform变量名称的最大长度。
    10. 其他参数,例如GL_PROGRAM_BINARY_RETRIEVABLE_HINT等等。
  3. params:指向存储返回参数值的变量的指针。

  • glDeleteProgram

        glDeleteProgram是OpenGL中删除着色器程序对象的函数之一。它的作用是删除已经创建的着色器程序对象,释放显存中的资源。具体来说,glDeleteProgram函数有一个参数:

void glDeleteProgram(GLuint program);
  1. program:要删除的着色器程序对象的ID。

2.举个例子

GLuint CreateProgram(GLuint vsShader, GLuint fsShader) {GLuint program = glCreateProgram();glAttachShader(program, vsShader);glAttachShader(program, fsShader);glLinkProgram(program);glDetachShader(program, vsShader);glDetachShader(program, fsShader);GLint nResult;glGetProgramiv(program, GL_LINK_STATUS, &nResult);if (nResult == GL_FALSE) {char log[1024] = { 0 };GLsizei writed = 0;glGetProgramInfoLog(program, 1024, &writed, log);printf("create gpu program fail,link error : %s\n", log);glDeleteProgram(program);program = 0;}return program;
}

五、读取shader源码到GPU程序

GLuint program;
void Init()
{//...//准备绘图数据//...int fileSize = 0;unsigned char * shaderCode = LoadFileContent("Res/test.vs", fileSize);GLuint vsShader = CompileShader(GL_VERTEX_SHADER, (char*)shaderCode);delete shaderCode;shaderCode = LoadFileContent("Res/test.fs", fileSize);GLuint fsShader = CompileShader(GL_FRAGMENT_SHADER, (char*)shaderCode);delete shaderCode;program = CreateProgram(vsShader, fsShader);glDeleteShader(vsShader);glDeleteShader(fsShader);
}

六、读取shader中的变量

1.相关函数

  • glGetUniformLocation

        glGetUniformLocation是OpenGL中用于获取Uniform变量的位置(或插槽)的函数之一。它用于查询指定着色器程序对象中的Uniform变量的位置,以便后续对其进行赋值。具体来说,glGetUniformLocation函数有两个参数:

GLint glGetUniformLocation(GLuint program, const GLchar *name);
  1. program:要查询Uniform变量的着色器程序对象的ID。
  2. name:Uniform变量的名称。(Uniform变量的名称必须与着色器程序中定义的Uniform变量的名称完全匹配。)
  • glGetAttribLocation

        glGetAttribLocation是OpenGL中用于获取Attribute变量的位置(或插槽)的函数之一。它用于查询指定着色器程序对象中的Attribute变量的位置,以便后续绑定顶点数据。具体来说,glGetAttribLocation函数有两个参数:

GLint glGetAttribLocation(GLuint program, const GLchar *name);
  1. program:要查询Attribute变量的着色器程序对象的ID。
  2. name:Attribute变量的名称。(Attribute变量的名称必须与着色器程序中定义的Attribute变量的名称完全匹配。)

2.举个例子

GLint positionLocation,modelMatrixLocation,viewMatrixLocation,projectionMatrixLocation;
void Init()
{//...//准备绘图数据//...//...//读取shader源码到GPU程序//...positionLocation = glGetAttribLocation(program, "position");modelMatrixLocation = glGetUniformLocation(program, "ModelMatrix");viewMatrixLocation = glGetUniformLocation(program, "ViewMatrix");projectionMatrixLocation = glGetUniformLocation(program, "ProjectionMatrix");
}

七、设置MVP矩阵

1.MVP矩阵

        在OpenGL中设置MVP(Model-View-Projection)矩阵是用于进行物体的变换和投影的重要步骤之一。通常,Model矩阵表示物体的模型变换,View矩阵表示摄像机的观察变换,而Projection矩阵表示投影变换。

        对于Model矩阵和View矩阵,默认是单位矩阵,所以不需要显式设置它们,可以通过使用glm库中的glm::mat4的默认构造函数创建单位矩阵。

        对于Projection矩阵,可以使用glm库中的glm::perspective函数来设置。

glm::mat4 glm::perspective(float fov, float aspect, float near, float far);
  1. fov:视野角度(Field of View),以弧度为单位。
  2. aspect:视口的宽高比(宽度除以高度)。
  3. near:近平面距离摄像机的距离。
  4. far:远平面距离摄像机的距离。

        该函数将返回一个透视投影矩阵,所有在近平面和远平面内且处于平截头体内的顶点都会被渲染。可以将其应用于Projection矩阵。

2.设置MVP矩阵

glm::mat4 modelMatrix, viewMatrix, projectionMatrix;
void SetViewPortSize(float width, float height)
{projectionMatrix = glm::perspective(glm::radians(45.0f), width / height, 0.1f, 1000.0f);
}

八、设置Uniform变量

1.glUniformMatrix4fv

        glUniformMatrix4fv是OpenGL中用于将4x4矩阵数据传递给Uniform变量的函数之一。它用于将一个或多个4x4矩阵值传递给在着色器程序中定义的Matrix4类型的Uniform变量。

void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
  1. location:要传递数据的Uniform变量的位置(或插槽)。
  2. count:要传递的矩阵数量。如果你只传递一个矩阵,则count为1。
  3. transpose:指定是否应该在传递矩阵之前对其进行转置。通常情况下,你可以将其设置为GL_FALSE。
  4. value:指向包含要传递数据的GLfloat数组的指针。矩阵数据按列主序存储在数组中。

2.代码示例

void Draw()
{glUseProgram(program);//启用着色器程序glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, glm::value_ptr(modelMatrix));   //将模型矩阵传递给着色器程序中的模型矩阵Uniform变量modelMatrixLocationglUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, glm::value_ptr(viewMatrix));    //将视图矩阵传递给着色器程序中的视图矩阵Uniform变量viewMatrixLocationglUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, glm::value_ptr(projectionMatrix));  //将投影矩阵传递给着色器程序中的投影矩阵Uniform变量projectionMatrixLocationglUseProgram(0);      //停用着色器程序
}

九、读取vbo数据,绘制三角形

1.相关函数

  • glVertexAttribPointer

        glVertexAttribPointer函数用于指定顶点属性的指针,并设置相关参数。

void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);

参数解释如下:

  1. index:顶点属性的索引,对应于着色器程序中的顶点属性变量。
  2. size:顶点属性的分量数量,例如3表示顶点属性由三个分量组成(如位置属性为x、y、z)。
  3. type:顶点属性的数据类型,例如GL_FLOAT表示浮点型数据。
  4. normalized:指定是否对非浮点型数据进行归一化处理,通常设置为GL_FALSE。
  5. stride:顶点属性之间的字节偏移量,用于在顶点数据中定位不同属性的数据。
  6. pointer:顶点属性数据的指针,指向顶点数据缓冲区中的起始位置。
  • glEnableVertexAttribArray

        glEnableVertexAttribArray函数用于启用指定索引的顶点属性数组。

void glEnableVertexAttribArray(GLuint index);

参数解释如下:

  1. index:顶点属性的索引,对应于着色器程序中的顶点属性变量。
  • glDrawArrays

        glDrawArrays函数用于执行基于顶点数组的图元绘制操作。

void glDrawArrays(GLenum mode, GLint first, GLsizei count);

参数解释如下:

  1. mode:指定绘制的图元类型,例如GL_POINTS表示绘制点,GL_TRIANGLES表示绘制三角形等。
  2. first:指定顶点数组中的起始索引,表示从哪个顶点开始绘制。
  3. count:指定要绘制的顶点数量。

2.代码示例

void Draw()
{glClearColor(0.0f, 1.0f, 0.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//...//设置Uniform变量//...glBindBuffer(GL_ARRAY_BUFFER, vbo);  //将顶点缓冲对象绑定到OpenGL的顶点缓冲区(GL_ARRAY_BUFFER)glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, 0);   //定义位置属性glEnableVertexAttribArray(positionLocation);  //启用位置属性索引为positionLocation的顶点属性数组glDrawArrays(GL_TRIANGLES, 0, 3);    //执行绘制操作。该函数指定了绘制的模式、起始顶点索引和顶点数量。glBindBuffer(GL_ARRAY_BUFFER, 0);    //解绑顶点缓冲对象
}

十、补充说明

        shader通常称为着色器,作用是把CPU上的点渲染出来,shader在GPU上是并行执行的,比如三个顶点的数据,会在三个core上并行处理。

        比如我们绘制一个三角形,需要三个顶点数据。顶点着色器将会被执行三次,每次使用不同的顶点数据作为输入。(不需要为每个顶点创建一个单独的vertex shader文件,我们可以使用相同的vertex shader文件来处理所有三个顶点,只需要为每个顶点提供不同的位置属性作为输入),并使用统一变量mvpMatrix进行模型-视图-投影变换。(即:position不一样,m、v、p矩阵相同

  • 3*4个数据的顶点矩阵,三个顶点:
    float data[] = {-0.2f,-0.2f,-0.6f,1.0f,0.2f,-0.2f,-0.6f,1.0f,0.0f,0.2f,-0.6f,1.0f};
  • vertex shader文件: 
attribute vec4 position;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

相关文章:

OpenGL进阶 | 绘制一个三角形

一、准备绘图数据 VBO(Vertex Buffer Object) 在opengl中,所有的数据都要放在显存中,通过VBO(Vertex Buffer Object)可将CPU数据传到GPU。 VBO(Vertex Buffer Object)是OpenGL中的一…...

CSAPP Lab3- bufbomb

实验目标 (1)掌握函数调用时的栈帧结构 (2)利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使得程序执行我们所期望的过程 实验代码 (1)makecookie:生成c…...

分布式系统之CAP定理介绍

前言 在分布式系统的设计和实现中,CAP定理是一个非常重要的概念。本文将介绍CAP定理的概念、含义和应用。 什么是 CAP 定理? CAP定理是分布式系统设计中的一个基本原则,它指出,在分布式系统中,一致性(Consi…...

vcomp140.dll怎么安装?提示vcomp140.dll丢失怎样修复?

在用电脑玩游戏或者打开软件工作的时候,电脑提示vcomp140.dll丢失无法执行此代码,是什么回事呢?需要怎么修复呢?不用紧张,小编今天就把vcomp140.dll文件修复方法分享给大家。我总结了几个修复经验; vcomp14…...

CA OpenSSL自签名证书(服务器/客户端)

参考文章 https://juejin.cn/post/7092789498823573518 https://blog.csdn.net/mengting2040/article/details/120001810 目录 使用 OpenSSL 生成证书创建根证书创建 Root Pair创建 Root Key创建 Root Crt 创建服务器端证书创建服务器端keyip需要换成自己服务器的外网ip地址&am…...

计算机视觉(4)—— 未有深度学习之前

目录 四、未有深度学习之前 4.1 图像分割 4.1.1 基于阈值分割 4.1.2 基于边缘分割 4.1.3 基于区域分割 (1)区域生长法 (2)分水岭算法 4.1.4 基于图论分割 (1)Graph Cuts 分割 ​(2&…...

怎么获取winform中动态代码生成的控件的状态

winform怎么获取动态代码生成窗口里面的控件的属性状态 MainForm中调用 private void ShowPropertyForm() { PropertyForm form new PropertyForm(selectedShape); form.ShowDialog(); pictureBox1.Refresh(); …...

Windows安装Maven并配置环境

Windows下安装和配置Maven的步骤 介绍:步骤:步骤 1:下载Maven步骤 2:解压缩Maven分发包步骤 3:设置环境变量步骤 4:验证安装 结论: 介绍: Maven是一个非常流行的构建和项目管理工具…...

致力于中小企业JavaEE企业级快速开发平台、后台框架平台

一、开源项目简介 J2eeFAST 是一个 Java EE 企业级快速开发平台, 致力于打造中小企业最好用的开源免费的后台框架平台 。系统基于(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)经典技术开发&…...

【神经网络】tensorflow实验9--分类问题

1. 实验目的 ①掌握逻辑回归的基本原理,实现分类器,完成多分类任务; ②掌握逻辑回归中的平方损失函数、交叉熵损失函数以及平均交叉熵损失函数。 2. 实验内容 ①能够使用TensorFlow计算Sigmoid函数、准确率、交叉熵损失函数等&#xff0c…...

LeetCode2. 两数相加

写在前面: 题目链接:LeetCode2两数相加 编程语言:C 题目难度:中等 一、题目描述 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 …...

基于无线传感网络(WSN)的目标跟踪技术(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 无线传感器网络由于其自组织性、鲁棒性及节点数量巨大的特点,非常适合于目标跟踪。无线传感器网络中的移动目标跟踪实际上就是…...

百度发布首个可信AI工具集TrustAI,助力数据分析与增强

百度发布首个集分析与增强于一体的可信AI工具集TrustAI,该工具集旨在帮助用户快速、准确地对各种类型的数据进行分析和增强,从而提高数据的价值和可信度。 随着人工智能技术的快速发展,数据的价值和重要性日益凸显。然而,在数据处…...

电力系统负荷与电价预测优化模型(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

asp.net+C#超市商品进销存管理系统

本超市商品管理系统主要超市内部提供服务,系统分为管理员员工两部分。 本研究课题重点主要包括了下面几大模块:管用户登录,员工管理,商品管理,进货管理,销售管理,供应商信息,会员信…...

轻量级K8s发行版的五大优势,助力企业快速拥抱边缘计算

随着物联网和移动设备的普及,边缘计算已成为当前信息技术领域的热门话题。为了满足这一需求,越来越多的企业开始探索使用容器化技术来打造轻量级的K8s发行版。这种发行版可以更加灵活地部署在物理边缘,提供更快速、更稳定的服务。 在这篇文章…...

【深入理解redis】数据结构

文章目录 动态字符串SDS字符串编码类型 intsetDictZipListZipList的连锁更新问题 QuickListSkipListRedisObjectStringListSet结构ZSETHash Redis 共有 5 种基本数据结构:String(字符串)、List(列表)、Set(…...

《计算机网络—自顶向下方法》 第三章Wireshark实验:DNS协议分析

域名系统 DNS(Domain Name System) 是互联网使用的命名系统,用于把便于大家使用的机器名字转换为 IP 地址。许多应用层软件经常直接使用 DNS,但计算机的用户只是间接而不是直接使用域名系统。 互联网采用层次结构的命名树作为主机的名字,并使…...

JUC(十二)-线程中断相关问题(LockSupport,sleep,InterruptException)

JUC线程中断相关问题总结 线程中断相关问题总结 JUC线程中断相关问题总结一、 sleep 和线程中断之间的关系和特点结论测试验证代码如下 二、 LockSupport 和线程中断之间的关系结论测试验证代码如下 一、 sleep 和线程中断之间的关系和特点 结论 线程调用 Thread.sleep之后会进…...

Kotlin高级协程

Kotlin高级协程 一.前言二.先从线程说起三.协程的设计思想四.协程特点:优雅的实现移步任务五.协程基本使用六.协程和线程相比有什么特点,如何优雅的实现异步任务 一.前言 在文章正式上干货之前,先说一点背景吧;我是 Kotlin 协程官…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线, n r n_r nr​ 根接收天线的 MIMO 系…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

C# 表达式和运算符(求值顺序)

求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...

Vue3 PC端 UI组件库我更推荐Naive UI

一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...