openGL学习(基本窗口)

学习路线 

学习 OpenGL 需要掌握一系列基础知识和技能,这些内容涵盖了计算机图形学的基本概念、编程语言、数学知识以及 OpenGL 的具体 API 使用。以下是学习 OpenGL 所需的主要知识点:

1. 计算机图形学基础

  • 图形学概念:了解图形学的基本概念,如像素、分辨率、颜色模型(RGB、RGBA)、光栅化、光栅图形等。

  • 图形管线:理解图形渲染管线的工作原理,包括顶点处理、光栅化、片段处理等阶段。

  • 图形对象:熟悉常见的图形对象,如点、线、多边形、纹理、光照等。

2. 数学基础

  • 线性代数

    • 向量:向量的基本运算(加法、减法、点积、叉积)。

    • 矩阵:矩阵的基本运算(乘法、逆矩阵、转置)。

    • 变换:平移、旋转、缩放等变换的矩阵表示。

  • 几何知识

    • 坐标系:理解世界坐标系、物体坐标系、视图坐标系、屏幕坐标系等。

    • 投影:正交投影和透视投影的概念及实现。

  • 光栅化算法

    • 直线绘制算法:如 Bresenham 算法。

    • 多边形填充算法:如扫描线填充算法。

3. 编程语言

  • C/C++:OpenGL 主要使用 C/C++ 进行编程,因此需要熟练掌握 C/C++ 的基本语法和编程技巧。

  • GLSL(OpenGL Shading Language):用于编写着色器程序,包括顶点着色器、片段着色器等。

4. OpenGL API

  • OpenGL 基础

    • 初始化:创建窗口、初始化 OpenGL 上下文(可以使用 GLFW 等库)。

    • 状态管理:了解 OpenGL 的状态机模型,如何设置和查询状态。

    • 缓冲区对象:如顶点缓冲区对象(VBO)、顶点数组对象(VAO)、帧缓冲区对象(FBO)等。

  • 着色器编程

    • 着色器类型:顶点着色器、片段着色器、几何着色器等。

    • 着色器程序:编写、编译、链接着色器程序。

    • 变量传递:如何将数据从 CPU 传递到 GPU(如 uniform 变量、attribute 变量)。

  • 渲染技术

    • 基本渲染:绘制点、线、三角形等基本图形。

    • 纹理映射:加载和应用纹理,理解纹理坐标、纹理过滤、纹理环绕等概念。

    • 光照:理解光照模型(如 Phong 照明模型),实现平行光、点光源、环境光等。

    • 阴影:实现阴影映射等高级光照效果。

  • 高级技术

    • 曲面细分:使用曲面细分着色器生成更平滑的曲面。

    • 计算着色器:用于通用计算任务。

    • 多视口渲染:在多个视口同时渲染不同的场景。

    • 后处理效果:如模糊、HDR、抗锯齿等。

5. 辅助工具和库

  • GLFW:用于创建窗口和处理输入。

  • GLAD:用于加载 OpenGL 函数指针。

  • GLM(OpenGL Mathematics):用于处理数学运算,如向量和矩阵运算。

  • FreeGLUT:用于创建窗口和处理输入(与 GLFW 类似)。

  • Assimp:用于加载 3D 模型文件。

  • SOIL:用于加载纹理文件。

6. 调试和优化

  • 调试工具:使用调试工具(如 RenderDoc、gDEBugger)来调试 OpenGL 程序。

  • 性能优化:了解常见的性能瓶颈(如 CPU/GPU 瓶颈、内存带宽瓶颈)和优化方法。

7. 实践项目

  • 小型项目:从简单的项目开始,如绘制一个旋转的立方体。

  • 复杂项目:逐步实现更复杂的场景,如加载 3D 模型、实现简单的游戏引擎等。

学习资源推荐

  • 书籍

    • 《OpenGL SuperBible》:适合初学者和进阶学习者。

    • 《OpenGL Programming Guide》(红宝书):经典教材。

  • 在线教程

    • LearnOpenGL:非常详细的 OpenGL 教程,适合初学者。

    • OpenGL Tutorial:包含丰富的示例和代码。

  • 视频教程

    • YouTube 上有许多 OpenGL 教程,如 The Cherno 的 OpenGL 系列。

初试OpenGL

1.首先需要编译glfw-3.4的动态库,和glad库,使用vs2021进行程序编写。

#include <iostream>
//#include "thrirdParty/include/GLFW/glfw3.h"
#include "glad/glad.h"   //需要先引用glad的头文件。
#include "GLFW/glfw3.h"using namespace std;
/*
* 创建glfw的窗体系统
*/
int main(int argc,char**argv)
{cout << "===================================" << endl;//1. 初始化GLFW基本环境glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//启用核心模式(非立即渲染模式)glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 2. 创建窗体对象GLFWwindow* win = glfwCreateWindow(800, 600, "OpenGlStudy", NULL, NULL);//设置窗体对象为Opengl的绘制舞台glfwMakeContextCurrent(win);// // 3. 执行窗体循环// while (!glfwWindowShouldClose(win)){//接受并且分发窗体消息//检查消息队列是否有需要处理的鼠标,键盘等信息//如果有的话就将消息批量处理,清空队列。glfwPollEvents();}// 4. 退出程序前做相关清理glfwTerminate();cout << "===================================" << endl;return 0;
}

 CMakeLists.txt

cmake_minimum_required(VERSION 3.12)project(OpenGL_Lecture)set(CMAKE_CXX_STANDARD 11)include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/thrirdParty/include
)
link_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/thrirdParty/lib)
add_executable(openglStudy "main.cpp" "glad.c")target_link_libraries(openglStudy glfw3.lib)

 事件响应

#include <iostream>
//#include "thrirdParty/include/GLFW/glfw3.h"
#include "glad/glad.h"   //需要先引用glad的头文件。
#include "GLFW/glfw3.h"using namespace std;
/*
* 创建glfw的窗体系统
* 加入窗体变化的事件回调
*/void frameBufferSizeCallback(GLFWwindow* win, int width, int height)
{std::cout << "窗体的最新大小为:" << width << "高度为:" << height << std::endl;}void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){// key 字母按键码 // scancode 物理按键码		 // action:0抬起1按下2长按// mods:是否有shift(1)或ctrl(2) cout << "key = " << key << " scancode = " << scancode << " action = " << action << " mods = " << mods << endl;if (key == GLFW_KEY_W){//按下了w}else if (action == GLFW_PRESS){//按下了}else if (action == GLFW_RELEASE){//抬起}}int main(int argc,char**argv)
{cout << "===================================" << endl;//1. 初始化GLFW基本环境glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//启用核心模式(非立即渲染模式)glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 2. 创建窗体对象GLFWwindow* win = glfwCreateWindow(800, 600, "OpenGlStudy", NULL, NULL);//设置窗体对象为Opengl的绘制舞台glfwMakeContextCurrent(win);//设置监听帧缓冲窗口大小回调函数。glfwSetFramebufferSizeCallback(win, frameBufferSizeCallback);glfwSetKeyCallback(win, keyCallback);// // 3. 执行窗体循环// while (!glfwWindowShouldClose(win)){//接受并且分发窗体消息//检查消息队列是否有需要处理的鼠标,键盘等信息//如果有的话就将消息批量处理,清空队列。glfwPollEvents();}// 4. 退出程序前做相关清理glfwTerminate();cout << "===================================" << endl;return 0;
}

函数加载

Opengl运行环境是一个巨大的状态机,每一个函数都会改变状态机的状态或者触发其执行某个行为。

OpenGL采用双缓冲机制 ,利用两个缓冲区进行交替展示。

#include <iostream>
//#include "thrirdParty/include/GLFW/glfw3.h"
#include "glad/glad.h"   //需要先引用glad的头文件。
#include "GLFW/glfw3.h"using namespace std;
/*
* 创建glfw的窗体系统
* 加入窗体变化的事件回调
*/void frameBufferSizeCallback(GLFWwindow* win, int width, int height)
{std::cout << "窗体的最新大小为:" << width << "高度为:" << height << std::endl;//更新窗体的大小glViewport(0, 0, width, height);}void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){// key 字母按键码 // scancode 物理按键码		 // action:0抬起1按下2长按// mods:是否有shift(1)或ctrl(2) cout << "key = " << key << " scancode = " << scancode << " action = " << action << " mods = " << mods << endl;if (key == GLFW_KEY_W){//按下了w}else if (action == GLFW_PRESS){//按下了}else if (action == GLFW_RELEASE){//抬起}}int main(int argc,char**argv)
{cout << "===================================" << endl;//1. 初始化GLFW基本环境glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//启用核心模式(非立即渲染模式)glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 2. 创建窗体对象GLFWwindow* win = glfwCreateWindow(800, 600, "OpenGlStudy", NULL, NULL);//设置窗体对象为Opengl的绘制舞台glfwMakeContextCurrent(win);//设置监听帧缓冲窗口大小回调函数。glfwSetFramebufferSizeCallback(win, frameBufferSizeCallback);glfwSetKeyCallback(win, keyCallback);// 使用glad加载所有当前版本的OpenGL函数,加载后才能使用if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) ) {cout << "Failed to initialize glad " << endl;}//设置OpenGL视口以及清理颜色glViewport(0,0,800,600);glClearColor(0.2f,0.3f,0.3f,1.0f);// 3. 执行窗体循环// while (!glfwWindowShouldClose(win)){//接受并且分发窗体消息glfwPollEvents();glClear(GL_COLOR_BUFFER_BIT);//渲染操作// //切换双缓冲glfwSwapBuffers(win);}// 4. 退出程序前做相关清理glfwTerminate();cout << "===================================" << endl;return 0;
}

OpenGL函数错误处理

main.cpp

#include <iostream>
//#include "thrirdParty/include/GLFW/glfw3.h"
#include "glad/glad.h"   //需要先引用glad的头文件。
#include "GLFW/glfw3.h"
#include <assert.h>
#include "wrapper/checkerror.h"using namespace std;/*
* 创建glfw的窗体系统
* 加入窗体变化的事件回调
*/void frameBufferSizeCallback(GLFWwindow* win, int width, int height)
{std::cout << "窗体的最新大小为:" << width << "高度为:" << height << std::endl;//更新窗体的大小glViewport(0, 0, width, height);}void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){// key 字母按键码 // scancode 物理按键码		 // action:0抬起1按下2长按// mods:是否有shift(1)或ctrl(2) cout << "key = " << key << " scancode = " << scancode << " action = " << action << " mods = " << mods << endl;if (key == GLFW_KEY_W){//按下了w}else if (action == GLFW_PRESS){//按下了}else if (action == GLFW_RELEASE){//抬起}}int main(int argc,char**argv)
{cout << "===================================" << endl;//1. 初始化GLFW基本环境glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//启用核心模式(非立即渲染模式)glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 2. 创建窗体对象GLFWwindow* win = glfwCreateWindow(800, 600, "OpenGlStudy", NULL, NULL);//设置窗体对象为Opengl的绘制舞台glfwMakeContextCurrent(win);//设置监听帧缓冲窗口大小回调函数。glfwSetFramebufferSizeCallback(win, frameBufferSizeCallback);glfwSetKeyCallback(win, keyCallback);// 使用glad加载所有当前版本的OpenGL函数,加载后才能使用if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress) ) {cout << "Failed to initialize glad " << endl;}//设置OpenGL视口以及清理颜色glViewport(0,0,800,600);glClearColor(0.2f,0.3f,0.3f,1.0f);// 3. 执行窗体循环// while (!glfwWindowShouldClose(win)){//接受并且分发窗体消息glfwPollEvents();GL_CALL( glClear(GL_COLOR_BUFFER_BIT) );//glClear(-1);//设置错误颜色不会崩溃,会出现黑色//checkError();//GL_CALL(glClear(-1) ); //渲染操作// //切换双缓冲glfwSwapBuffers(win);}// 4. 退出程序前做相关清理glfwTerminate();cout << "===================================" << endl;return 0;
}

wrapper/checkerror.cpp

头文件checkerror.h就是void checkError();

#include "checkerror.h"
#include "glad/glad.h"
#include <string>
#include <iostream>
#include <assert.h>using namespace std;void checkError()
{GLenum errornum = glGetError();//cout << "errornum = " << errornum << endl; //错误码1281 GL_INVALID_VALUEstd::string errorstr = "";if (errornum != GL_NO_ERROR){cout << "GL有错误" << endl;switch (errornum){case GL_INVALID_ENUM:errorstr = "无效的枚举 GL_INVALID_ENUM"; break;case GL_INVALID_VALUE:errorstr = "无效的值 GL_INVALID_VALUE"; break;case GL_INVALID_OPERATION:errorstr = "无效的操作 GL_INVALID_OPERATION"; break;case GL_OUT_OF_MEMORY:errorstr = "无效的内存 GL_OUT_OF_MEMORY"; break;default:errorstr = "UNKNOWN";break;}cout << "errorstr = " << errorstr << endl;assert(false); //断言根据bool决定是否停止程序。}
}

./CMakeLists.txt

cmake_minimum_required(VERSION 3.12)project(OpenGL_Lecture)set(CMAKE_CXX_STANDARD 11)include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/thrirdParty/include
)
link_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/thrirdParty/lib)add_subdirectory(wrapper)#在项目夹加入全局的预编译宏
add_definitions(-DCHECK_ERROR)add_executable(openglStudy "main.cpp" "glad.c" )target_link_libraries(openglStudy glfw3.lib wrapper)

wrapper/CMakeLists.txt

#递归将本文件夹下的所有cpp放到WRAPPER中file(GLOB_RECURSE WRAPPER ./ *.cpp)#将所有cpp文件链接到这个wrapper lib库中。 默认生成静态库,动态库编译不过去
add_library(wrapper    ${WRAPPER})

Application封装

 application.cpp

#include "application.h"
#include "application.h"
#include "application.h"#include "glad/glad.h"   //需要先引用glad的头文件。 用于加载 OpenGL 函数指针
#include "GLFW/glfw3.h" // 用于创建窗口和处理输入。	Application* Application::m_app = nullptr;
Application* Application::getInst()
{if (m_app == nullptr){m_app = new Application();}return m_app;
}int Application::init(const int width, const int height)
{cout << "Application::init" << endl;m_Width = width;m_Height = height;//1. 初始化GLFW基本环境glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);//启用核心模式(非立即渲染模式)glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);// 2. 创建窗体对象m_Window = glfwCreateWindow(m_Width, m_Height, "OpenGlStudy", NULL, NULL);if (m_Window == NULL){return -1;}//设置窗体对象为Opengl的绘制舞台glfwMakeContextCurrent(m_Window);// 使用glad加载所有当前版本的OpenGL函数,加载后才能使用if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){cout << "Failed to initialize glad " << endl;return -1;}//GLFW监听必须要使用static进行声明。//窗口大小改变的事件glfwSetFramebufferSizeCallback(m_Window, frameBufferSizeCallback);//键盘的事件glfwSetKeyCallback(m_Window, keyCallback);//this就是全局Application对象glfwSetWindowUserPointer(m_Window, this);//将this暂时存在窗体中。return 0;
}int Application::update()
{if (glfwWindowShouldClose(m_Window)){return -1;}//接受并且分发窗体消息glfwPollEvents();//切换双缓冲glfwSwapBuffers(m_Window);return 0;
}int Application::destroy()
{cout << "Application::destroy" << endl;// 4. 退出程序前做相关清理glfwTerminate();return 0;
}Application::Application()
{}void Application::frameBufferSizeCallback(GLFWwindow* win, int width, int height)
{//因为是静态函数,所以不能调用全局唯一实例。// 静态成员函数属于类本身,而不是类的某个具体对象。//它不依赖于任何对象实例,因此不能访问非静态成员变量//(因为非静态成员变量需要对象实例来存储其值)。cout << "frameBufferSizeCallback " << endl;//m_resizeCallBack();// //面试题:如何在静态成员函数中调用非静态函数?//if(Application::getInst()->m_resizeCallBack != nullptr)//	Application::getInst()->m_resizeCallBack(width,height);Application* self  = (Application*) glfwGetWindowUserPointer(win);if(self->m_resizeCallBack != nullptr)self->m_resizeCallBack(width, height);}void Application::keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{cout << "keyCallback " << endl;Application* self = (Application*)glfwGetWindowUserPointer(window);if (self->m_keyCallBack != nullptr)self->m_keyCallBack(window, key,scancode,action,mods);}Application::~Application()
{}

application.h

#pragma once#include <iostream>#define app Application::getInst()class GLFWwindow; //提前声明class,避免头文件重复定义的问题.using resizeCallBack = void(*)(int width,int height);
using keyCallBack = void(*)(GLFWwindow* window,int key, int scancode, int action, int mods);using namespace std;//单例类实现class Application
{
public:~Application();static Application* getInst();void test() { cout << "test" << endl; };uint32_t getWidth() const { return m_Width; }; //const含义:不改变类中的成员uint32_t getHeight() const { return m_Height; };int init(const int width = 800, const int height = 500);int update();int destroy(); void setResizeCallBack(resizeCallBack call) { m_resizeCallBack = call; };void setkeyCallBack(keyCallBack call) { m_keyCallBack = call; };private:Application();static Application* m_app;uint32_t m_Width{ 0 }; //列表初始化uint32_t m_Height{ 0 };GLFWwindow* m_Window{ nullptr };resizeCallBack m_resizeCallBack{nullptr};keyCallBack m_keyCallBack{ nullptr };private:static void frameBufferSizeCallback(GLFWwindow*win,int width,int height);static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);};

main.cpp

#include <iostream>
//#include "thrirdParty/include/GLFW/glfw3.h" 
#include "glad/glad.h"   //需要先引用glad的头文件。 用于加载 OpenGL 函数指针
#include "GLFW/glfw3.h" // 用于创建窗口和处理输入。	
#include <assert.h>
#include "wrapper/checkerror.h"
#include "application/application.h"using namespace std;/*
* 创建glfw的窗体系统
* 加入窗体变化的事件回调
*/void onResize(int width,int height)
{GL_CALL(glViewport(0, 0, width, height));cout << "onResize " << endl;
}void frameBufferSizeCallback(GLFWwindow* win, int width, int height)
{std::cout << "窗体的最新大小为:" << width << "高度为:" << height << std::endl;//更新窗体的大小glViewport(0, 0, width, height);}void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods){// key 字母按键码 // scancode 物理按键码		 // action:0抬起1按下2长按// mods:是否有shift(1)或ctrl(2) cout << "key = " << key << " scancode = " << scancode << " action = " << action << " mods = " << mods << endl;if (key == GLFW_KEY_W){//按下了w}else if (action == GLFW_PRESS){//按下了}else if (action == GLFW_RELEASE){//抬起}}int main(int argc,char**argv)
{cout << "===================================" << endl;if (app->init(800,600) == -1){return -1;}//设置监听帧缓冲窗口大小回调函数。//glfwSetFramebufferSizeCallback(win, frameBufferSizeCallback);//glfwSetKeyCallback(win, keyCallback);app->setResizeCallBack(onResize);app->setkeyCallBack(keyCallback);//设置OpenGL视口以及清理颜色glViewport(0,0,800,600);glClearColor(0.2f,0.3f,0.3f,1.0f);// 3. 执行窗体循环// while (app->update() == 0 ){GL_CALL( glClear(GL_COLOR_BUFFER_BIT) );//渲染操作}// 4. 退出程序前做相关清理app->destroy();cout << "===================================" << endl;return 0;
}

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

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

相关文章

无人机防护装置技术解析

一、技术要点 1. 侦测防御系统 多频谱复合探测 整合无线电侦测&#xff08;20MHz–6GHz频段扫描&#xff09;、雷达探测、光电跟踪&#xff08;可见光/红外/激光&#xff09;技术&#xff0c;实现360无死角监测。例如神州明达系统可5公里内识别无人机信号&#xff0c;并同步…

2.2.2、CAN总线-测试模式、工作模式

目录 1、测试模式 2、工作模式 &#xff08;1&#xff09; &#xff08;2&#xff09;SLEEP位&#xff1a; &#xff08;3&#xff09;INRQ位&#xff1a;&#xff08;Init Request&#xff09; &#xff08;4&#xff09;ACK&#xff1a;应答 &#xff08;5&#xff09;…

区块链大讲堂 | 分布式隐私计算友好的零知识证明协议

区块链大讲堂 主讲人&#xff1a;上海交通大学计算机学院助理教授胡云聪 报告题目&#xff1a;分布式隐私计算友好的零知识证明协议 参与方式&#xff1a;扫描海报二维码报名参与活动

MyBatis映射文件(XML)中参数传递和SQL特殊字符处理

1. 参数占位符 1.1 #{} 和 ${} 的区别 #{} 占位符 作用&#xff1a;安全传参。MyBatis在执行SQL时&#xff0c;会把#{}替换成?&#xff0c;然后用参数值自动填充。 优点&#xff1a;可以防止SQL注入&#xff0c;推荐使用。 例子&#xff1a; select * from user wher…

C语言 数据结构 --排序 (直接插入排序,选择排序,交换排序......)

引言&#xff1a;本章简洁的讲解一下数据结构中的几个常见的排序 &#xff0c;作复习之用&#xff0c;后面可能会补一些其他的排序 。并给出一些小编学习中遇到的坑&#xff0c;作借鉴。 1.直接插入排序 直接插入排序是一种简单直观的排序算法&#xff0c;其基本思想是将一个数…

华为云发布盘古大模型 5.5 新一代昇腾 AI 云服务上线

2025 年 6 月 20 日&#xff0c;华为开发者大会 2025&#xff08;HDC 2025&#xff09;在东莞召开。华为常务董事、云计算 CEO 张平安宣布基于 CloudMatrix 384 超节点的新一代昇腾 AI 云服务全面上线&#xff0c;并发布盘古大模型 5.5&#xff0c;五大基础模型实现技术突破&am…

Reactor Handle

handle 是 Reactor 中一个非常灵活的操作符&#xff0c;它允许你对每个源元素进行处理&#xff0c;并可以选择性地发出零个或多个元素。它既可以用于映射&#xff08;map&#xff09;也可以用于过滤&#xff08;filter&#xff09;&#xff0c;因此可以看作是 map 和 filter 的…

C#哈希加密:原理、实现与应用

C#哈希加密&#xff1a;原理、实现与应用 在当今数字化时代&#xff0c;数据安全是每个应用程序都必须重视的问题。哈希加密作为一种重要的加密技术&#xff0c;在密码存储、数据完整性验证、数字签名等领域发挥着关键作用。本文将深入探讨C#中哈希加密的原理、常用算法以及实…

httpbin.org是什么,有什么作用

httpbin.org 是一个开源的 HTTP 请求与响应测试服务&#xff0c;基于 Python 的 Flask 框架开发 它允许开发者发送各种 HTTP 请求&#xff0c;并返回请求的详细信息&#xff0c;便于调试和验证 HTTP 客户端的行为。以下是其核心功能和作用详解&#xff1a; 一、核心功能与作用…

mongodb生产备份工具PBM

如果你的 MongoDB 数据量特别大&#xff08;例如几十 GB、TB 级别&#xff09;&#xff0c;普通的 mongodump/mongorestore 会显得缓慢且资源消耗大&#xff0c;不适合生产级别大数据集。下面是当前 MongoDB 社区和企业广泛使用的几种备份方案对比和推荐&#xff1a; 工具是否…

【LeetCode#第167题】两数之和Ⅱ

给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 < numbers…

Python(一)实现一个爬取微信小程序数据的爬虫+工程化初步实践

文章目录 前言用Charles 抓包 iOS 微信小程序在Mac端和iOS端安装Charles 自签名证书Mac端iOS端 能抓到Safari浏览器的包但是抓不到微信小程序的包直接在iOS 上抓包的App如何抓取Android 7.0 以上/Harmony OS微信小程序包 Python 项目工程化pip 切换为国内镜像源工程化参考脚手架…

uview ui request get / post 传参含params和json数据的分析和使用

背景。单独写了controller方法去配合移动端的接口调用。但有的接口与pc端类似。于是进行了复用。但接口得复制不是。 uview js request 文档 注意迪三个参数是header 后端接口GET方法 调用代码截图 浏览器调试 总结。 复制之前的api接口。为了方便复用底层实现。接口类型…

用 pnpm + TurboRepo,构建多项目高效开发体系

在现代前端项目日益复杂的今天&#xff0c;我们越来越多地面对一个场景&#xff1a;多个项目共享逻辑、组件和依赖&#xff0c;而维护和构建效率却在不断拉垮。这种情况下&#xff0c;传统项目结构的痛点就显现无遗。 从我亲身实践来看&#xff0c;选择 pnpm TurboRepo 构建 …

Pytest 使用命令行参数执行指定环境的脚本—— Python 实践

&#x1f9fe; 一、项目背景 在自动化测试中&#xff0c;我们经常需要根据不同的运行环境&#xff08;如测试环境和生产环境&#xff09;来执行测试脚本。本文将详细介绍如何通过命令行参数来指定运行环境&#xff0c;并使用 Python 和 pytest 框架实现这一功能。 &#x1f6e…

利用可控验证码位数实现拒绝服务攻击(DoS)风险与线程模型分析

一、背景介绍&#xff1a;验证码接口中的潜在 DoS 漏洞 在渗透测试过程中&#xff0c;常见验证码接口支持传入“验证码位数”参数&#xff0c;表面看是业务可配置&#xff0c;实则若未做上限控制&#xff0c;极易成为资源消耗型 DoS 攻击入口。 &#x1f9ea; 测试场景&#…

Spring Cloud Feign 整合 Sentinel 实现服务降级与熔断保护

Spring Cloud Feign 整合 Sentinel 实现服务降级与熔断保护 在微服务架构中&#xff0c;服务之间的调用往往依赖 Feign&#xff0c;而服务调用的稳定性又至关重要。本文将介绍如何将 Feign 与 Sentinel 结合使用&#xff0c;实现服务的容错保护&#xff08;如降级与熔断&#…

宠物医院系统的设计与实现(springBoot版)

一、开题报告 一、本选题研究的意义和背景&#xff08;理论与现实意义&#xff09;&#xff1a; 背景&#xff1a;随着人们生活水平的提高&#xff0c;宠物饲养愈发普遍&#xff0c;宠物医院的需求也日益增长。挂号方式主要依赖现场挂号&#xff0c;导致宠物主人需要长时间排队…

SOCKSv5 协议通信的完整阶段与报文格式详解

SOCKSv5 协议的通信通常分为以下几个主要阶段&#xff1a; 方法协商阶段 (Method Negotiation)方法依赖的子协商阶段 (Method-Dependent Sub-negotiation) - 本例为用户名/密码认证请求发送阶段 (Request Sending)请求回复阶段 (Request Reply)数据传输阶段 (Data Transfer) …

​​Git提交代码Commit消息企业级规范

​​Git Commit 类型完整指南​​ 类型用途示例​​feat​​新增功能&#xff08;面向用户的功能性变更&#xff09;git commit -m "feat: 添加用户登录功能"​​fix​​修复 Bug&#xff08;解决代码中的问题&#xff09;git commit -m "fix: 修复首页加载崩溃…