OpenGL —— 2.6、绘制一个正方体并贴图(附源码,glfw+glad)
源码效果
C++源码
纹理图片
需下载stb_image.h这个解码图片的库,该库只有一个头文件。
具体代码:
vertexShader.glsl
#version 330 corelayout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aUV;out vec2 outUV;uniform mat4 _viewMatrix;
uniform mat4 _projMatrix;void main()
{gl_Position = _projMatrix * _viewMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);outUV = aUV;
}
fragmentShader.glsl
#version 330 coreout vec4 FragColor;in vec2 outUV;uniform sampler2D ourTexture;void main()
{// 使用图片纹理及色彩混合FragColor = texture(ourTexture, outUV);
}
main.cpp
#include "OpenGLClass.h"
#include "OpenGLClass.h"int main()
{OpenGLClass opengl;return 0;
}
OpenGLClass.h
#pragma once#include "Global.h"
#include "ffImage.h"class OpenGLClass
{
public:OpenGLClass();~OpenGLClass();protected:// 初始化纹理bool initTexture();// 初始化模型VAO/VBOvoid initModel();// 初始化shader文件bool initShader(const char *_vertexPath, const char *_fragPath);// 读取glsl文件内容std::string ReadGlslContext(const char *sPath);// 刷新Rendervoid FlushRender();// 回调 - 窗口尺寸变化回调static void bck_GLFWframebuffersizefun(GLFWwindow* window, int width, int height);// 处理按键输入void ProcessKeyPInput(GLFWwindow *window);// 设置矩阵void setMatrix(const std::string &_name, glm::mat4 _matrix)const;private:unsigned short windowWidth = 800, windowHeight = 600;unsigned int shaderProgram = 0; // 链接程序对象unsigned int VBO = 0, VAO = 0, _texture = 0;
};
OpenGLClass.cpp
#include "OpenGLClass.h"void OpenGLClass::bck_GLFWframebuffersizefun(GLFWwindow* window, int width, int height)
{// 在窗口中定义一个像素矩形,最终的图形将映射到个矩形中glViewport(0, 0, width, height);
}OpenGLClass::OpenGLClass()
{// 初始化glfw上下文if (glfwInit() == GLFW_FALSE) { std::cout << "glfwInit fail!\n"; return; }glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 3.3版本glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用OpenGL核心模式// 创建OpenGL窗体GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, "OpenGL Core", nullptr, nullptr);if (!window) { std::cout << "glfwCreateWindow fail!\n"; return; }// 当前OpenGL上下文绑定窗口glfwMakeContextCurrent(window);// 加载所有OpenGL函数指针if (GL_FALSE == gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "gladLoadGLLoader fail!\n"; return; }// 在窗口中定义一个像素矩形,最终的图形将映射到个矩形中glViewport(0, 0, windowWidth, windowHeight);// 窗口大小调整回调glfwSetFramebufferSizeCallback(window, OpenGLClass::bck_GLFWframebuffersizefun);// 初始化VAO/VBOinitModel();// 初始化纹理if (!initTexture()) { std::cout << "initTexture fail!\n"; system("pause"); return; }// 初始化shaderif (!initShader("vertexShader.glsl", "fragmentShader.glsl")) { std::cout << "initShader fail!\n"; system("pause"); return; }// 窗口标志是否是关闭while (!glfwWindowShouldClose(window)){// 输入按键处理ProcessKeyPInput(window);#if 0// 使用红,绿,蓝以及alpha值来清除颜色缓冲区glClearColor(0.328125f, 0.35156f, 0.82421f, 1.0f);// 将从窗口中清除最后一次所绘制的图形/*GL_COLOR_BUFFER_BIT: 当前可写的颜色缓冲GL_DEPTH_BUFFER_BIT: 深度缓冲GL_ACCUM_BUFFER_BIT: 累积缓冲GL_STENCIL_BUFFER_BIT: 模板缓冲*/glClear(GL_COLOR_BUFFER_BIT);
#endifFlushRender();// 双缓冲,使用OpenGL或OpenGL ES进行渲染glfwSwapBuffers(window);// glfw事件循环glfwPollEvents();// 睡眠10ms,防止造成GPU疯狂消耗。实际具体调整Sleep(10);}// 释放窗口glfwDestroyWindow(window);// 释放资源,终止GLFW库glfwTerminate();
}OpenGLClass::~OpenGLClass()
{// 释放if (glIsProgram(shaderProgram)) { glDeleteProgram(shaderProgram); }shaderProgram = 0;if (glIsBuffer(VAO)) { glDeleteBuffers(1, &VAO); } VAO = 0;if (glIsBuffer(VBO)) { glDeleteBuffers(1, &VBO); } VBO = 0;
}void OpenGLClass::ProcessKeyPInput(GLFWwindow *window)
{if (window){// 获取窗口按键是否ESCif (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){// 设置窗口关闭标志glfwSetWindowShouldClose(window, true);}}window = nullptr;
}void OpenGLClass::setMatrix(const std::string &_name, glm::mat4 _matrix) const
{// 获得指定shader程序中uniform变量的位置int shaderNameId = glGetUniformLocation(shaderProgram, _name.c_str());/*将4x4的矩阵数据传递给着色器location:指定要更改的uniform变量的位置。count:指定要更改的矩阵的数量。如果只更改一个矩阵,该值为1。transpose:指定是否需要将矩阵进行转置。一般情况下,设为GL_FALSE即可。value:指向包含矩阵数据的指针。*/glUniformMatrix4fv(shaderNameId,1,GL_FALSE,glm::value_ptr(_matrix));
}void OpenGLClass::FlushRender()
{// 判断VAO是否被删除if (glIsVertexArray(VAO)){// 使用红,绿,蓝以及alpha值来清除颜色缓冲区glClearColor(0.328125f, 0.35156f, 0.82421f, 1.0f);// 将从窗口中清除最后一次所绘制的图形,GL_DEPTH_BUFFER_BIT将深度信息也清除glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 开启深度检测glEnable(GL_DEPTH_TEST);///// 观察者/摄像机矩阵glm::mat4 _viewMatrix = glm::lookAt(glm::vec3(1.4f, 1.4f, 2.0f), // 摄像机位置glm::vec3(0.0f, 0.0f, 0.0f), // 摄像机看向的位置glm::vec3(0.0f, 1.0f, 0.0f) // 摄像机顶部的位置);// 投影矩阵glm::mat4 _projMatrix = glm::perspective(glm::radians(45.0f),(float)windowWidth / (float)(windowHeight),0.1f, 100.0f);///// 使用程序glUseProgram(shaderProgram);///setMatrix("_viewMatrix", _viewMatrix);setMatrix("_projMatrix", _projMatrix);///// 绑定纹理glBindTexture(GL_TEXTURE_2D, _texture);// 绑定VAOglBindVertexArray(VAO);// 绘制三角形glDrawArrays(GL_TRIANGLES, 0, 36);// 关闭使用程序glUseProgram(0);}
}bool OpenGLClass::initTexture()
{// 读取图片相关信息ffImage *pImage = ffImage::readFromFile("./rec/wall.jpeg");if (!pImage) { return false; }// 生成纹理glGenTextures(1, &_texture);// 以2D方式绑定纹理// 将当前绑定的纹理对象替换为参数中指定的纹理对象glBindTexture(GL_TEXTURE_2D, _texture);// 设置纹理属性glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 读取图片数据,完成数据绑定glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pImage->getWidth(), pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pImage->getData());if (pImage) { delete pImage; }pImage = nullptr;return true;
}void OpenGLClass::initModel()
{// 坐标、纹理位置float vertices[]{-0.5f,-0.5f,-0.5f, 0.0f,0.0f,0.5f,-0.5f,-0.5f, 1.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,1.0f,0.5f, 0.5f,-0.5f, 1.0f,1.0f,-0.5f, 0.5f,-0.5f, 0.0f,1.0f,-0.5f,-0.5f,-0.5f, 0.0f,0.0f,-0.5f,-0.5f,0.5f, 0.0f,0.0f,0.5f,-0.5f,0.5f, 1.0f,0.0f,0.5f, 0.5f,0.5f, 1.0f,1.0f,0.5f, 0.5f,0.5f, 1.0f,1.0f,-0.5f, 0.5f,0.5f, 0.0f,1.0f,-0.5f,-0.5f,0.5f, 0.0f,0.0f,-0.5f, 0.5f, 0.5f, 1.0f,0.0f,-0.5f, 0.5f,-0.5f, 1.0f,1.0f,-0.5f,-0.5f,-0.5f, 0.0f,1.0f,-0.5f,-0.5f,-0.5f, 0.0f,1.0f,-0.5f,-0.5f, 0.5f, 0.0f,0.0f,-0.5f, 0.5f, 0.5f, 1.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f,0.0f,0.5f, 0.5f,-0.5f, 1.0f,1.0f,0.5f,-0.5f,-0.5f, 0.0f,1.0f,0.5f,-0.5f,-0.5f, 0.0f,1.0f,0.5f,-0.5f, 0.5f, 0.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f,0.0f,-0.5f,-0.5f,-0.5f, 0.0f,1.0f,0.5f,-0.5f,-0.5f, 1.0f,1.0f,0.5f,-0.5f, 0.5f, 1.0f,0.0f,0.5f,-0.5f, 0.5f, 1.0f,0.0f,-0.5f,-0.5f, 0.5f, 0.0f,0.0f,-0.5f,-0.5f,-0.5f, 0.0f,1.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f,0.5f,0.5f,-0.5f, 1.0f,1.0f,0.5f,0.5f, 0.5f, 1.0f,0.0f,0.5f,0.5f, 0.5f, 1.0f,0.0f,-0.5f,0.5f, 0.5f, 0.0f,0.0f,-0.5f,0.5f,-0.5f, 0.0f,1.0f};/****************************************************/ // VAO// 创建VAOglGenVertexArrays(1, &VAO);// 绑定指定的顶点数组对象(Vertex Array Object, VAO)glBindVertexArray(VAO);/****************************************************//****************************************************/ // VBO// 生成缓冲区对象glGenBuffers(1, &VBO);// 绑定命名缓冲区对象glBindBuffer(GL_ARRAY_BUFFER, VBO);// 缓冲对象(VBO,IBO 等)分配空间并存储数据glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);/*指定顶点属性在顶点缓冲对象中的布局,并将其与顶点着色器中的顶点属性进行关联参数1:第n个layout (对应glsl中顶点着色器的layout)参数2:顶点属性的组成元素的数量,例如3表示顶点属性是由3个浮点数组成参数3:顶点属性的数据类型参数4:是否将非浮点型的数据归一化到[-1, 1]或[0, 1]范围内参数5:相邻两个顶点属性之间的字节数,通常为0或属性类型大小乘以数量参数6:顶点属性在顶点缓冲对象中的偏移量或者数据的首地址*/glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(sizeof(float) * 3));// 激活锚点(参数:第n个layout)glEnableVertexAttribArray(0);glEnableVertexAttribArray(1);// 解绑VAO/VBOglBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);/****************************************************/
}std::string OpenGLClass::ReadGlslContext(const char *sPath)
{std::string strContext;if (!sPath) { return strContext; }std::ifstream sFile;sFile.open(sPath);if (sFile.is_open()){std::stringstream sStream;sStream << sFile.rdbuf();strContext = sStream.str();}return strContext;
}bool OpenGLClass::initShader(const char *_vertexPath, const char *_fragPath)
{char infoLog[512] = { 0 };int successFlag = 0;/*********************************************************/ // vertex编译std::string vertexContext = ReadGlslContext(_vertexPath); if (vertexContext.empty()) { return false; }const char *cVertexContext = vertexContext.c_str();// 创建顶点着色器对象unsigned int iVertexID = glCreateShader(GL_VERTEX_SHADER);// 为顶点着色器指定源码(参数2:传过去几个)glShaderSource(iVertexID, 1, &cVertexContext, nullptr);// 编译顶点着色器源码glCompileShader(iVertexID);// 查看编译顶点着色器源码结果glGetShaderiv(iVertexID, GL_COMPILE_STATUS, &successFlag);if (!successFlag) // 编译失败{// 获取编译失败原因glGetShaderInfoLog(iVertexID, 512, nullptr, infoLog);std::cout << "glGetShaderiv GL_VERTEX_SHADER" << iVertexID << " fail:" << infoLog << std::endl; return false;}cVertexContext = nullptr;/*********************************************************//*********************************************************/ // fragment编译std::string fragmentContext = ReadGlslContext(_fragPath); if (fragmentContext.empty()) { return false; }const char *cFragmentContext = fragmentContext.c_str();// 创建片段着色器对象unsigned int iFragmentID = glCreateShader(GL_FRAGMENT_SHADER);// 为片段着色器指定源码(参数2:传过去几个)glShaderSource(iFragmentID, 1, &cFragmentContext, nullptr);// 编译片段着色器源码glCompileShader(iFragmentID);// 查看编译片段着色器源码结果glGetShaderiv(iFragmentID, GL_COMPILE_STATUS, &successFlag);if (!successFlag) // 编译失败{// 获取编译失败原因glGetShaderInfoLog(iFragmentID, 512, nullptr, infoLog);std::cout << "glGetShaderiv GL_FRAGMENT_SHADER" << iFragmentID << " fail:" << infoLog << std::endl; return false;}cFragmentContext = nullptr;/*********************************************************//*********************************************************/ // 链接// 创建一个空的程序对象shaderProgram = glCreateProgram();if (shaderProgram == 0) { std::cout << "glCreateProgram fail!\n"; return false; }// 将着色器对象附加到程序对象上(注:glDetachShader为移除程序对象中的指定着色器对象)glAttachShader(shaderProgram, iVertexID);glAttachShader(shaderProgram, iFragmentID);// 进行链接程序对象glLinkProgram(shaderProgram);// 查看链接状态glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successFlag);if (!successFlag) // 链接失败{// 获取链接失败原因glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);std::cout << "glGetProgramiv " << shaderProgram << " fail:" << infoLog << std::endl; return false;}/*********************************************************//* 在链接完成后,将编译shader相关删除。仅留下链接ID */if (glIsShader(iVertexID)) { glDeleteShader(iVertexID); }if (glIsShader(iFragmentID)) { glDeleteShader(iFragmentID); }return true;
}
完整源码下载
源码下载
关注
Wx GZH:码农总动员
笔者 - jxd
相关文章:

OpenGL —— 2.6、绘制一个正方体并贴图(附源码,glfw+glad)
源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec2 aUV;out vec2 outUV;uniform mat4 _viewMatrix; u…...

JavaWeb从入门到起飞笔记——导学课程
学完这一节,我不知道学Web开发究竟能干什么?你知道吗? 以下是黑马程序员Java从入门到起飞的笔记 一、学完Javaweb能干什么? 学完Java后我们可以独立开发一些后台管理系统,例如CRMER器,京东和淘宝&#x…...

【LeetCode:1402. 做菜顺序 | 动态规划 + 贪心】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...

基于FPGA的图像拉普拉斯变换实现,包括tb测试文件和MATLAB辅助验证
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a vivado2019.2 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 202…...

高校教务系统登录页面JS分析——巢湖学院
高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文,你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习,勿用于非法用途。 一、密码加…...

人工智能、机器学习、深度学习的区别
人工智能涵盖范围最广,它包含了机器学习;而机器学习是人工智能的重要研究内容,它又包含了深度学习。 人工智能(AI) 人工智能是一门以计算机科学为基础,融合了数学、神经学、心理学、控制学等多个科目的交…...

Element Plus el-select选择框失去焦点blur
正常情况下,可以使用 el-select 自带的方法 blur 事件来使select失去焦点 示例: <el-select v-model"value" ref"selectRef"><el-optionv-for"item in options":key"item.value":label"item.la…...

Java File与IO流学习笔记
内存中存放的都是临时数据,但是在断电或者程序终止时都会丢失 而硬盘则可以长久存储数据,即使断电,程序终止,也不会丢失 File File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文…...

LabVIEW中PID控制的的高级功能
LabVIEW中PID控制的的高级功能 比例-积分-微分(PID)控制占当今控制和自动化应用的90%以上,主要是因为它是一种有效且简单的解决方案。虽然PID算法最初用于线性、时不变系统,但现在已经发展到控制具有复杂动力学的系统。在现实世界…...

STM32基于HAL库RT-Thread Demo测试
STM32基于HAL库RT-Thread Demo测试 🎈源码地址:https://github.com/RT-Thread/rt-thread/tree/master📌基于STM32CUBEMX中间件安装《基于 CubeMX 移植 RT-Thread Nano》📍环境搭建《使用 Env 创建 RT-Thread 项目工程》ǵ…...
萌新小白必做题(2)找素数
一.思路分析 先来看看素数的性质: 素数又称质数,是指除了1和本身外没有其它因数的自然数。素数有许多有趣的性质和应用,例如可以用于加密算法和数学证明等。比如2、3、5、7等都是素数,而4、6、8、9等则不是素数。素数的研究是数…...
《基于 Vue 组件库 的 Webpack5 配置》8.在生成打包文件之前清空 output(dist) 目录(两种方式)
方式一 如果 webpack 是 v5.20.0,直接使用属性 output.clean,配置如下: module.exports {//...output: {clean: true}, };方式二 如果使用较低版本,可以使用插件 clean-webpack-plugin: 先安装:npm…...

3、Kafka Broker
4.1 Kafka Broker 工作流程 4.1.1 Zookeeper 存储的 Kafka 信息 (1)启动 Zookeeper 客户端。 [hadoop102 zookeeper-3.5.7]$ bin/zkCli.sh(2)通过 ls 命令可以查看 kafka 相关信息。 [zk: localhost:2181(CONNECTED) 2] ls /kaf…...

数字孪生智慧建筑可视化系统,提高施工效率和建造质量
随着科技的不断进步和数字化的快速发展,数字孪生成为了建筑行业的一个重要的概念,被广泛应用于智能化建筑的开发与管理中。数字孪生是将现实世界的实体与数字世界的虚拟模型进行连接和同步,从而实现实时的数据交互和模拟仿真。数字孪生在建筑…...

SpringCloud: feign整合sentinel实现降级
一、加依赖: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache…...
List<LinkedHashMap<String, String>>类型的数据转换为Map<String, List<String>>类型数据
import java.util.*;public class Main {public static void main(String[] args) {// 示例数据:List<LinkedHashMap>List<LinkedHashMap<String, String>> keyParamList new ArrayList<>();LinkedHashMap<String, String> map1 ne…...

react 学习 —— 16、使用 ref 操作 DOM
什么时候使用 ref 操作 DOM? 有时你可能需要访问由 React 管理的 DOM 元素 —— 例如,让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。 怎么使用 r…...

Qt planeGame day10
Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用,我们需要自己搭框架首先创建一个QGame类作为框架,这个基本框架里面应该有如下功能:游戏初始化 void init(const QSize& siez,const QString& title);游戏反初始化(…...

贪吃蛇项目实践
游戏背景: 贪吃蛇是久负盛名的游戏,它也和俄罗斯⽅块,扫雷等游戏位列经典游戏的⾏列。 实现基本的功能: 贪吃蛇地图绘制 蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作) 蛇撞墙死亡 蛇撞⾃⾝死亡 计…...

【C++】哈希应用——海量数据面试题
哈希应用——海量数据面试题 一、位图应用1、给定100亿个整数,设计算法找到只出现一次的整数?2、给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?(1)用一个位图…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...