CMake创建跨平台OpenGL工程(学习笔记)

一、跨平台环境基本配置

1、环境搭建

1)linux OpenGL环境搭建参考:ubuntu18.04 OpenGL开发(显示YUV)_ubuntu opengl-CSDN博客

https://blog.51cto.com/cerana/6433535

本文使用的是QTCreator

2)windows下环境搭建

OpenGL+Visual Studio2022+GLFW+glad详细配置教程_给vs配置glfw和glad-CSDN博客

 本文是用的是QTCreator或者vs2022。

2、创建cmake

    这里测试使用的图形界面使用QT。其中路径后面讲解

    主要有几个注意事项:

1)linux下需要添加

 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-error=register")

2)windows下需要设置vitual studio

set(LIBRARY_GLFW_PATH "${PROJECT_SOURCE_DIR}/lib-vc2022")

cmake_minimum_required(VERSION 3.5)

SET(TARGET "QTGL")

project(${TARGET} VERSION 0.1 LANGUAGES CXX)

#设置QT安装路径
if(WIN32)
	set(QT5_CMAKE_PATH "D:\\Qt\\Qt5.14.2\\5.14.2\\msvc2017_64\\lib\\cmake")
elseif()
	
endif()

set(Qt5_DIR "${QT5_CMAKE_PATH}/Qt5")
set(Qt5Core_DIR "${QT5_CMAKE_PATH}/Qt5Core")
set(Qt5Widgets_DIR "${QT5_CMAKE_PATH}/Qt5Widgets")
set(Qt5UiTools_DIR "${QT5_CMAKE_PATH}/Qt5UiTools")
set(Qt5PrintSupport_DIR "${QT5_CMAKE_PATH}/Qt5PrintSupport")
set(Qt5Svg_DIR "${QT5_CMAKE_PATH}/Qt5Svg")

#


set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
                                                                                                                       
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(WIN32)
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-error=register")
endif()

set(QTGL_GLAPI_PATH "${PROJECT_SOURCE_DIR}/GLAPI")
set(GLAD_FOLDER_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/glad/include")
set(GLAD_FOLDER_SOURCE_PATH  "${PROJECT_SOURCE_DIR}/glad/src")
set(GLM_FOLDER_INCLUDE_PATH  "${PROJECT_SOURCE_DIR}/glm")
set(GLFW_FOLDER_INCLUDE_PATH  "${QTGL_GLAPI_PATH}/glfw")

if(WIN32)
    set(LIBRARY_GLFW_PATH "${PROJECT_SOURCE_DIR}/lib-vc2022")
    LINK_DIRECTORIES("${LIBRARY_GLFW_PATH}")
endif()

include_directories(${QTGL_GLAPI_PATH})
include_directories(${GLAD_FOLDER_INCLUDE_PATH})
include_directories(${GLM_FOLDER_INCLUDE_PATH})
include_directories(${GLFW_FOLDER_INCLUDE_PATH})

file(GLOB GLAPI_HEADERS "${QTGL_GLAPI_PATH}/*.h")
source_group("GLAPI/include" FILES ${GLAPI_HEADERS})

file(GLOB GLAPI_SOURCES "${QTGL_GLAPI_PATH}/*.cpp")
source_group("GLAPI/source" FILES ${GLAPI_SOURCES})

file(GLOB_RECURSE GLAD_INCLUDE "${GLAD_FOLDER_INCLUDE_PATH}/*.*")
source_group("glad/include" FILES ${GLAD_INCLUDE})

file(GLOB GLAD_SOURCE "${GLAD_FOLDER_SOURCE_PATH}/*.*")
source_group("glad/src" FILES ${GLAD_SOURCE})

SET(QTUI_PATH "${PROJECT_SOURCE_DIR}/QTUI")

file(GLOB_RECURSE QTUI_FILES "${QTUI_PATH}/*.*")
source_group("QTUI" FILES ${QTUI_FILES})


set(ALL_SOURCES
        ${GLAPI_HEADERS}
        ${GLAPI_SOURCES}
        ${GLAD_INCLUDE}
        ${GLAD_SOURCE}
        ${QTUI_FILES}
)

ADD_EXECUTABLE(${TARGET} WIN32 ${ALL_SOURCES})

find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)

target_link_libraries(${TARGET} PRIVATE Qt5::Widgets Qt5::Core Qt5::Gui)

if(WIN32)
    target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3.lib")
    target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3_mt.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3_mt.lib")
    target_link_libraries(${TARGET} PRIVATE debug "${LIBRARY_GLFW_PATH}/glfw3dll.lib" optimized "${LIBRARY_GLFW_PATH}/glfw3dll.lib")
else()
    target_link_libraries(${TARGET} PRIVATE glfw3)
    target_link_libraries(${TARGET} PRIVATE GL)
    target_link_libraries(${TARGET} PRIVATE X11)
    target_link_libraries(${TARGET} PRIVATE m)
    target_link_libraries(${TARGET} PRIVATE pthread)
    target_link_libraries(${TARGET} PRIVATE dl)
endif()

3、第三方库文件

1)glad和glm

glad下载:https://glad.dav1d.de/,下载后得到glad.zip

把glad整个文件夹放置到工程目录下,然后,把src下的glad.c改为glad.cpp。

把glm整个文件夹放置到工程目录下,不需要额外的修改。

2)glfw

glfw下载,Download | GLFW

windows下,需要将编译好的glfw库放置到工程下。如图:

 3)整体工程结构如图:

4、QT界面文件QTUI

创建一个QDialog或者QMainWindow,带有.ui文件,可以使用uic指令将其转换为.h文件。

cmake中需要配置QT安装路径: Qt5_DIR关键字,同时需要配置QT5相关的模块:

find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)

target_link_libraries(${TARGET} PRIVATE Qt5::Widgets Qt5::Core Qt5::Gui)

注意:QT6的配置和QT5不同,这里用的QT5。

二、OPENGL 简单示例

1、初始化工程

1)初始化glfw,具体解释看:OpenGL学习(一) 绘制一个三角形 - 简书

int DrawApi::initialGlfw()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // glad: load all OpenGL function pointers
    
    return 0;
}

2)创建窗口:

int DrawApi::createWindow(string windowName, OUT GLFWwindow*& window)
{
    // glfw window creation
    // --------------------
    window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, windowName.c_str(), NULL, NULL);
    if (window == NULL)
    {
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        cout << "Failed to initialize GLAD" << endl;
        return -1;
    }

    glViewport(0, 0, 800, 800);

    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);  // 窗体能够根据拉动变化

    return 0;
}

3)顶点着色器

int DrawApi::createVertexShader(OUT GLuint& vertexShader, const char* vertexShaderSource)
{
    //1.初始化着色器
    //创建一个着色器类型
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    //把代码复制进着色器中
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    //编译顶点着色器
    glCompileShader(vertexShader);

    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

    //判断是否编译成功
    if (!success) {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        cout << "error when vertex compile:" << infoLog << endl;
        return -1;
    }
    return 0;
}

4)片元着色器

int DrawApi::createFragmentShader(OUT GLuint& fragmentShader, const char* fragmentShaderSource)
{
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);

    glCompileShader(fragmentShader);

    int success;
    char infoLog[512];
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);

    //判断是否编译成功
    if (!success) {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        cout << "error when fragment compile:" << infoLog << endl;
        return -1;
    }
    return 0;
}

5)编译程序

int DrawApi::createProgram(GLuint& vertexShader, GLuint& fragmentShader, OUT GLuint& shaderProgram)
{
    //链接,创建一个程序
    shaderProgram = glCreateProgram();

    //链接上共享库
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    //链接
    glLinkProgram(shaderProgram);

    int success;
    char infoLog[512];
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        cout << "error when link compile:" << infoLog << endl;
        return -1;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    return 0;
}

6)绘制三角形

int DrawApi::drawTriangles(const vector<vector<float>>& triangelValues)
{
    //1.会先绑定顶点
    //2.绑定缓冲区
    //3.接着把顶点输入到顶点缓冲去中
    //4.把缓冲区的数据传送到着色器中
    //5.输出到屏幕。

    if (initialGlfw() < 0)
        return -1;

    GLFWwindow* window = nullptr;
    if (createWindow("learnOpenGL", window) < 0)
        return -2;

    GLuint vertexShader;
    if (createVertexShader(vertexShader, VERTEX_SHADER) < 0)
        return -3;

    GLuint fragmentShader;
    if (createFragmentShader(fragmentShader, FRAGMENT_SHADER) < 0)
        return -4;

    GLuint shaderProgram;
    if (createProgram(vertexShader, fragmentShader, shaderProgram) < 0)
        return -5;

    if (triangelValues.size() == 0)
        return -6;

    if (triangelValues.size() > 1256)
        return -7;

    float vertices[4096] = {0};

    for (int i = 0; i < triangelValues.size(); i++)
    {
        for (int j = 0; j < 3; j++)
        {
             vertices[3 * i + j] = triangelValues[i][j];
        }
    }

    GLuint VAO;
    // 生成分配VAO
    glGenVertexArrays(1, &VAO);
    // 绑定VAO,注意在core模式,没有绑定VAO,opengl拒绝绘制任何东西
    glBindVertexArray(VAO);

    GLuint VBO;
    // 生成一个VBO缓存对象
    glGenBuffers(1, &VBO);
    // 绑定VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 类型为GL_ARRAY_BUFFER 第二第三参数说明要放入缓存的多少,GL_STATIC_DRAW当画面不动的时候推荐使用
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

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

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        processInput(window);

        // render
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);


        glUseProgram(shaderProgram);
        //绑定数据
        glBindVertexArray(VAO);
        //绘制一个三角形
        //从0开始,3个
        glDrawArrays(GL_TRIANGLES, 0, triangelValues.size() * 3);

        glBindVertexArray(0);

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

2、读取shader文件

shader着色器文件保存成vsCode能识别的js文件。如图:

 编写读取函数:

    // 返回错误码,strPath为文件路径,shaderTxt返回的文件内容
    std::string readShader(std::string strPath, std::string& shaderTxt)
    {
        std::ifstream ifs;
        ifs.open(strPath, std::ios::in);

        if (!ifs.is_open())
        {
            return "file open failed";
        }

        std::string textContent;
        while (getline(ifs, textContent))
        {
            shaderTxt += textContent;
            shaderTxt += '\n';
        }

        return "";
    }

 使用shader代码示例:

   GLuint vertexShader;

    std::string strVertexShader;
    std::string errStr = m_shaderManger.readShader(m_shaderManger.getShaderPath() + "VERTEX_SHADER.js", strVertexShader);

    if (errStr.length() > 0)
    {
        return -1;
    }

    if (createVertexShader(vertexShader, strVertexShader.c_str()) < 0)
        return -3;

    std::string strFragmentShader;
    errStr = m_shaderManger.readShader(m_shaderManger.getShaderPath() + "FRAGMENT_SHADER.js", strFragmentShader);

    if (errStr.length() > 0)
    {
        return -1;
    }

    GLuint fragmentShader;
    if (createFragmentShader(fragmentShader, strFragmentShader.c_str()) < 0)
        return -4;

3、创建三角形的代码示例

这是创建有颜色的三角形其中Point和Color为自定义结构体

class Color
{
public:
	float m_r;
	float m_g;
	float m_b;
	Color(float r, float g, float b)
	{
		m_r = r;
		m_g = g;
		m_b = b;
	};
	void setColor(float r, float g, float b)
	{
		m_r = r;
		m_g = g;
		m_b = b;
	};
};

class Point
{
public:
	float m_x;
	float m_y;
	float m_z;

	Point(float x, float y, float z)
	{
		m_x = x;
		m_y = y;
		m_z = z;
	};
	void setPoint(float x, float y, float z)
	{
		m_x = x;
		m_y = y;
		m_z = z;
	};
};

函数入参设置成vector,每一个值即为一个带颜色的点,每三个值就是一个三角形。因此使用的时候可以传入多个三角形。

int DrawApi::drawColorTriangle(vector < std::pair< Point, Color > > triPoints)
{
    if (initialGlfw() < 0)
        return -1;

    GLFWwindow* window = nullptr;
    if (createWindow("learnOpenGL", window) < 0)
        return -2;

    GLuint vertexShader;
    if (createVertexShader(vertexShader, VERTEX_COLOR_SHADER) < 0)
        return -3;

    GLuint fragmentShader;
    if (createFragmentShader(fragmentShader, FRAGMENT_COLOR_SHADER) < 0)
        return -4;

    GLuint shaderProgram;
    if (createProgram(vertexShader, fragmentShader, shaderProgram) < 0)
        return -5;

    if (triPoints.size() != 3)
        return -6;

    float vertices[18] = {0};

    int vertiCnt = 0;
    for (int i = 0; i < triPoints.size(); i++)
    {
         vertices[vertiCnt++] = triPoints[i].first.m_x;
         vertices[vertiCnt++] = triPoints[i].first.m_y;
         vertices[vertiCnt++] = triPoints[i].first.m_z;

         vertices[vertiCnt++] = triPoints[i].second.m_r;
         vertices[vertiCnt++] = triPoints[i].second.m_g;
         vertices[vertiCnt++] = triPoints[i].second.m_b;
    }

    GLuint VAO;
    // 生成分配VAO
    glGenVertexArrays(1, &VAO);
    // 绑定VAO,注意在core模式,没有绑定VAO,opengl拒绝绘制任何东西
    glBindVertexArray(VAO);

    GLuint VBO;
    // 生成一个VBO缓存对象
    glGenBuffers(1, &VBO);
    // 绑定VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 类型为GL_ARRAY_BUFFER 第二第三参数说明要放入缓存的多少,GL_STATIC_DRAW当画面不动的时候推荐使用
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    //第五个参数表示了一开始读取数据时的偏移量,坐标不需要变动,颜色则是离开头偏移了3个loat
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    //glBindBuffer(GL_ARRAY_BUFFER, 0);
    //glBindVertexArray(0);
    //glBindVertexArray(1);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // input
        processInput(window);

        // render
      /*  glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);*/

        glUseProgram(shaderProgram);
        //绑定数据
        glBindVertexArray(VAO);

        //绘制一个三角形
        //从0开始,3个
        glDrawArrays(GL_TRIANGLES/*GL_TRIANGLES*/, 0, 3);

        glBindVertexArray(0);

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();

        //float timeValue = glfwGetTime();                 //获取时间
        //float redValue = (sin(timeValue) / 3.0f) + 0.6f;
        //float greenValue = (sin(timeValue) / 2.0f) + 0.5f;  //利用sin和时间实现颜色值在0-1之间变换
        //float blueValue = sin(timeValue);
        //int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");  //获取shader中的ourColor变量
        //glUniform4f(vertexColorLocation, redValue, greenValue, blueValue, 1.0f);  //修改ourColor的值

    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

使用时如下所示:

{
    vector < std::pair< Point, Color > > triPoints;
    triPoints.push_back({Point(-0.5, -0.5, 0.3), Color(1.0, 0.0, 0.0)});
    triPoints.push_back({Point(0.5, -0.5, 0.3), Color(0.0, 1.0, 0.0)});
    triPoints.push_back({Point(0.0, 0.5, -0.3), Color(0.3, 0.0, 1.0) });

    m_drawApi.drawColorTriangle(triPoints);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

三. TensorRT基础入门-ONNX注册算子的方法

目录 前言0. 简述1. 执行一下我们的python程序2.转换swin-tiny时候出现的不兼容op的例子3. 当出现导出onnx不成功的时候&#xff0c;我们需要考虑的事情4. unsupported asinh算子5. unsupported deformable conv算子总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战…

新能源行业网间数据交换,更好用更专业的工具是什么?

新能源行业涵盖了多个方面&#xff0c;包括但不限于新能源汽车、可再生能源技术等。新能源行业发展具有重要的意义&#xff0c;新能源企业的研发数据极其重要&#xff0c;为了保障网络安全和数据安全&#xff0c;许多新能源企业采用逻辑隔离的方式进行网络隔离&#xff0c;此时…

C#【进阶】泛型

1、泛型 文章目录 1、泛型1、泛型是什么2、泛型分类3、泛型类和接口4、泛型方法5、泛型的作用思考 泛型方法判断类型 2、泛型约束1、什么是泛型2、各泛型约束3、约束的组合使用4、多个泛型有约束思考1 泛型实现单例模式思考2 ArrayList泛型实现增删查改 1、泛型是什么 泛型实现…

08 - hive的集合函数、高级聚合函数、炸裂函数以及窗口函数

目录 1、集合函数 1.1、size&#xff1a;集合中元素的个数 1.2、map&#xff1a;创建map集合 1.3、map_keys&#xff1a; 返回map中的key 1.4、map_values: 返回map中的value 1.5、array 声明array集合 1.6、array_contains: 判断array中是否包含某个元素 1.7、sort_a…

SBM模型、超效率SBM模型代码及案例数据(补充操作视频)

01、数据简介 SBM&#xff08;Slack-Based Measure&#xff09;模型是一种数据包络分析&#xff08;Data Envelopment Analysis, DEA&#xff09;的方法&#xff0c;用于评估决策单元&#xff08;Decision Making Units, DMUs&#xff09;的效率。而超效率SBM模型是对SBM模型的…

告别数据泥潭:PySpark性能调优的黄金法则

阿佑今天给大家带来个一张藏宝图——使用PySpark进行性能调优的黄金法则&#xff0c;从内存管理到执行计划&#xff0c;再到并行度设置&#xff0c;每一步都是提升数据处理速度的关键&#xff01; 文章目录 Python Spark 详解1. 引言2. 背景介绍2.1 大数据处理技术演变2.2 Apac…

Flutter-加载中动画

效果 考察内容 AnimationControllerTweenAnimatedBuilderTransformMatrix4 实现 ///源码&#xff1a;https://github.com/yixiaolunhui/flutter_xy class LoadingView extends StatefulWidget {const LoadingView({Key? key}) : super(key: key);overrideState<LoadingV…

AI算法-高数5-线性代数1-基本概念、向量

线性代数&#xff1a;主要研究1、张量>CV计算机视觉 2、研究张量的线性关系。 深度学习的表现之所以能够超过传统的机器学习算法离不开神经网络&#xff0c;然而神经网络最基本的数据结构就是向量和矩阵&#xff0c;神经网络的输入是向量&#xff0c;然后通过每个矩阵对向量…

Vue3项目打包部署到云服务器的Nginx中

文章目录 一、打包vue3项目二、dist文件夹上传到服务器三、改nginx配置文件Docker安装nginx 一、打包vue3项目 npm run build 二、dist文件夹上传到服务器 将dist文件夹放到docker安装的nginx中的html目录下 三、改nginx配置文件 然后重启nginx【改了配置文件重启nginx才能…

Cloudflare国内IP地址使用教程

Cloudflare国内IP地址使用教程 加速网站&#xff1a; 首先我们添加一个 A 记录解析&#xff0c;解析 IP 就是我们服务器真实 IP&#xff1a; 然后侧边栏 SSL/TLS - 自定义主机名&#xff1a; 回退源这里填写你刚刚解析的域名&#xff0c;保存后回退源状态为有效再来接下的操作…

C++ 指针 参数 静态 常 友元与组合概念

一 类类型作为函数参数 1 类类型作参数类型的三种方式 1&#xff09; 对象本身作为参数 由于C采用传值的方式传递参数&#xff0c;因此使用对象本身参数时&#xff0c;形参是实参的一个拷贝。在这种情况下&#xff0c;最好显式地为类定义一个拷贝构造函数&#xff0c;以免出…

二维费用背包分组背包

二维费用背包&分组背包 一定要做的

[Spring Cloud] (7)gateway防重放拦截器

文章目录 简述本文涉及代码已开源Fir Cloud 完整项目防重放防重放必要性&#xff1a;防重放机制作用&#xff1a; 整体效果后端进行处理 后端增加防重放开关配置签名密钥 工具类防重放拦截器 前端被防重放拦截增加防重放开关配置请求头增加防重放签名处理防重放验证处理函数bas…

HC-06 蓝牙串口从机 AT 命令详解

HC-06 蓝牙串口从机 AT 命令详解 要使用 AT 命令&#xff0c;首先要知道 HC-06 的波特率&#xff0c;然后要进入 AT 命令模式。 使用串口一定要知道三要素&#xff0c;一是波特率&#xff0c;二是串口号&#xff0c;三是数据格式, HC-06只支持一种数据格式: 数据位8 位&#…

MYSQL数据库-SQL语句

数据库相关概念 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase(DB)数据库管理系统操纵和管理数据库的大型软件DataBase Management System(DBMS)SQL操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准Structured Quer…

第十四篇:数据库设计精粹:规范化与性能优化的艺术

数据库设计精粹&#xff1a;规范化与性能优化的艺术 1. 引言 1.1 数据库设计在现代应用中的核心地位 在数字化的浪潮中&#xff0c;数据库设计如同建筑师手中的蓝图&#xff0c;是构建信息大厦的基石。它不仅关乎数据的存储与检索&#xff0c;更是现代应用流畅运行的生命线。…

打印图形(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int i, j;//循环打印&#xff1b;for (i 0; i < 5; i){//列&#xff1b;for (j 0; j &…

Python深度学习基于Tensorflow(9)注意力机制

文章目录 注意力机制是怎么工作的注意力机制的类型 构建Transformer模型Embedding层注意力机制的实现Encoder实现Decoder实现Transformer实现 注意力机制的主要思想是将注意力集中在信息的重要部分&#xff0c;对重要部分投入更多的资源&#xff0c;以获取更多所关注目标的细节…

关于Speech processing Universal PERformance Benchmark (SUPERB)基准测试及衍生版本

Speech processing Universal PERformance Benchmark &#xff08;SUPERB&#xff09;是由台湾大学、麻省理工大学&#xff0c;卡耐基梅隆大学和 Meta 公司联合提出的评测数据集&#xff0c;其中包含了13项语音理解任务&#xff0c;旨在全面评估模型在语音处理领域的表现。这些…

贝叶斯分类器详解

1 概率论知识 1.1 先验概率 先验概率是基于背景常识或者历史数据的统计得出的预判概率&#xff0c;一般只包含一个变量&#xff0c;例如P(A)&#xff0c;P(B)。 1.2 联合概率 联合概率指的是事件同时发生的概率&#xff0c;例如现在A,B两个事件同时发生的概率&#xff0c;记…