OpenGL —— 2.7、绘制多个自旋转的贴图正方体(附源码,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 _modelMatrix;
uniform mat4 _viewMatrix;
uniform mat4 _projMatrix;void main()
{gl_Position = _projMatrix* _viewMatrix * _modelMatrix * 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::vec3 modelVecs[] ={glm::vec3(0.0f,0.0f,0.0f),glm::vec3(2.0f, 5.0f, -15.0f),glm::vec3(-1.5f, -2.2f, -2.5f),glm::vec3(-3.8f, -2.0f, -12.3f),glm::vec3(2.4f, -0.4f, -3.5f),glm::vec3(-1.7f, 3.0f, -7.5f),glm::vec3(1.3f, -2.0f, -2.5f),glm::vec3(1.5f, 2.0f, -2.5f),glm::vec3(1.5f, 0.2f, -1.5f),glm::vec3(-1.3f, 1.0f, -1.5f)};//////// 观察者/摄像机矩阵glm::mat4 _viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 2.4f), // 摄像机位置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);// 绘制10个立方体for (unsigned short index = 0; index < 10; ++index){glm::mat4 _modelMatrix(1.0f);_modelMatrix = glm::translate(_modelMatrix, modelVecs[index]);_modelMatrix = glm::rotate(_modelMatrix, glm::radians((float)glfwGetTime()*(index + 1) * 10), glm::vec3(0.5f, 1.0f, 0.0f));///setMatrix("_modelMatrix", _modelMatrix);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.7、绘制多个自旋转的贴图正方体(附源码,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 _modelMatrix; …...

linux之perf(8)annotate标注
Linux之perf(8)annotate标注 Author:Onceday Date:2023年10月12日 漫漫长路,才刚刚开始… 注:该文档内容采用了GPT4.0生成的回答,部分文本准确率可能存在问题。 参考文档: Tutorial - Perf Wiki (kernel.org)perf…...

【广州华锐互动】VR建筑安全培训体验为建筑行业人才培养提供有力支持
随着建筑行业的快速发展,建筑施工安全问题日益受到广泛关注。然而,传统的安全培训方式往往缺乏实践性和真实性,难以让员工真正掌握安全操作技能。近年来,虚拟现实(VR)技术的广泛应用为建筑施工安全培训提供了新的机遇。 虚拟现实技…...

【Javascript保姆级教程】运算符
文章目录 前言一、运算符是什么二、赋值运算符2.1 如何使用赋值运算符2.2 示例代码12.3 示例代码2 三、自增运算符3.1 运算符3.2 示例代码13.3 示例代码2 四、比较运算符4.1 常见的运算符4.2 如何使用4.3 示例代码14.4 示例代码2 五、逻辑运算符逻辑运算符列举 六、运算符优先级…...

图论与网络优化
2.概念与计算 2.1 图的定义 2.1.1 定义 图(graph) G G G 是一个有序的三元组,记作 G < V ( G ) , E ( G ) , ψ ( G ) > G<V(G),E(G),\psi (G)> G<V(G),E(G),ψ(G)>。 V ( G ) V(G) V(G) 是顶点集。 E ( G ) E(G) E(G) 是边集。 ψ ( G ) \…...

【论文复现】基于多模态深度学习方法的单细胞多组学数据聚类(【生物信息学】实验二:多组学数据融合:scMDC)
目录 一、实验介绍 1. 论文:基于多模态深度学习方法的单细胞多组学数据聚类 Abstract 2. Github链接 二、实验环境 0. 作者要求 1. 环境复现 实验一 实验二(本实验) 2. 库版本介绍 实验一 实验二 3. IDE 三、实验内容 1. 用法…...

mysql按指定字符截取
1、使用SUBSTRING函数进行截取 语法:str是要截取的字符串,pos是起始位置,len是要截取的长度 SUBSTRING(str, pos, len)例子 SELECT SUBSTRING(Hello, World!, 1, 5);返回"Hello"。其中,起始位置为1,截取的…...

搜索引擎-在URL地址栏输入信息,不跳转
在URL地址栏输入信息,不跳转 原因解决待续 原因 因为没有使用某个搜索引擎,无法定位到资源 解决 先打开百度或搜狗其他引擎,在输入内容,跳转成功 待续 ————————————————————— 以上就是今日博客的全部内容…...

10种新型网络安全威胁和攻击手法
2023年,网络威胁领域呈现出一些新的发展趋势,攻击类型趋于多样化,例如:从MOVEit攻击可以看出勒索攻击者开始抛弃基于加密的勒索软件,转向窃取数据进行勒索;同时,攻击者们还减少了对传统恶意软件…...

Elasticsearch:painless script 语法基础和实战
摘要:Elasticsearch,Java script的作用 script是Elasticsearch的拓展功能,通过定制的表达式实现已经预设好的API无法完成的个性化需求,比如完成以下操作 字段再加工/统计输出字段之间逻辑运算定义查询得分的计算公式定义特殊过…...

《数据结构、算法与应用C++语言描述》使用C++语言实现数组双端队列
《数据结构、算法与应用C语言描述》使用C语言实现数组双端队列 定义 队列的定义 队列(queue)是一个线性表,其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾(back或rear),删除元素的那一…...

TikTok Shop新结算政策:卖家选择权加强,电商市场蓄势待发
据悉,从2023年11月1日开始,TikTok Shop将根据卖家的店铺表现来应用3种不同类型的结算期,其中,标准结算期:资金交收期为8个日历日;快速结算期:资金交收期为3个日历日;延长结算期&…...

asp.net特色商品购物网站系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net特色商品购物网站系统 是一套完善的web设计管理系统,系统采用mvc模式(BLLDALENTITY)系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 vs2010,数据库为sqlserver2008&a…...

解决一则诡异的javascript函数不执行的问题
有个vue 音乐播放器项目,由于之前腾讯的搜索接口没法用了,于是改成了别家的搜索接口。 但是由于返回数据结构不一样,代码重构的工作量还是挺大的:包括数据请求,数据处理,dom渲染,处理逻辑都进行…...

汽车安全的未来:毫米波雷达在碰撞避免系统中的角色
随着科技的飞速发展,汽车安全系统变得愈加智能化,而毫米波雷达技术正是这一领域的亮点之一。本文将深入探讨毫米波雷达在汽车碰撞避免系统中的关键角色,以及其对未来汽车安全的影响。 随着城市交通的拥堵和驾驶环境的变化,汽车安全…...

体感互动游戏研发虚拟场景3D漫游
体感互动游戏是一种结合虚拟现实(VR)或增强现实(AR)技术的游戏,允许玩家以身体动作和姿势来与游戏互动。这种类型的游戏通常需要特殊的硬件设备,例如体感控制器、摄像头或传感器,以捕捉玩家的动…...

微信小程序获取手机号(2023年10月 python版)[无需订阅]
技术栈: 1. 微信开发者工具中的调试基础库版本:3.1.2。 2. 后台:django。 步骤: 1. 首先在后台django项目的定时任务中增加一个下载access_token函数,并把得到的access_token保存在数据库中(其实随便哪里…...

Linux下设置网关以及网络相关命令
一、临时设置网关 查看当前路由表:route -n设置网关:route add default gw <路由器的网关IP> 注意:系统重启时,这些更改将不生效 二、永久设置网关 列出可用网络连接:nmcli connection show设置网关&#x…...

linux三剑客~sed命令的使用
1.工作原理: sed是一种流编辑器,它是文本处理中非常有用的工具 能够完美的配合正则表达式使用,处理时,把当前处理的行存储在临时缓冲区中,称为模式空间,接着用sed命令处理缓冲区中的内容 处理完成后&…...

virtualBox虚拟机安装多个+主机访问虚拟机+虚拟机访问外网配置
目的:本机安装3个虚拟机 一、虚拟机安装:Oracle VM VirtualBox (https://www.virtualbox.org/)源代码可下载,且免费使用 1、https://www.virtualbox.org/ 进入网站中Download 模块选择与自己电脑系统相应的下载包下载即可 如果安装过程报错如…...

正点原子嵌入式linux驱动开发——Linux按键输入
在前几篇笔记之中都是使用的GPIO输出功能,还没有用过GPIO输入功能,本章就来学习一下如果在Linux下编写GPIO输入驱动程序。正点原子STM32MP1开发板上有三个按键,就使用这些按键来完成GPIO输入驱动程序,同时利用原子操作来对按键值进…...

java--强制类型转换
类型范围大的数据或者变量,直接赋值给小范围的变量,会报错 1.强制类型转换 强行将类型范围大的变量、数据赋值给类型范围小的变量 2.强制类型转换在计算机中的执行原理 解释说明1:a是int类型有8个字节32位,然后在执行下一行代码…...

java后端调用接口Basic auth认证
该方法接收一个JSON字符串参数phoneNum 内容: {"phone":"13712312312"} 然后解析参数中的手机号,作为data去调用URL接口,接收接口返回的复合JSON并解析,拿到想要的数据public String queryUserResumeURLIn…...

App爬虫之强大的Airtest的操作总结
App爬虫之强大的Airtest的操作总结 App爬虫之强大的Airtest的操作总结 # Python使用该框架需要安装的依赖库 pip install airtest pip install poco pip install pocouifrom airtest.core.api import * from airtest.cli.parser import cli_setup from poco.drivers.android.…...
MODBUS-TCP转MODBUS-RTU通信应用(S7-1200和串口服务器通信)
在学习本博客之前,大家需要熟悉MODBUS-TCP和MODBUS-RTU通信,这2个通信的编程应用,大家可以查看下面文章链接: MODBUS-RTU通信 MODBUS-RTU通信协议功能码+数据帧解读(博途PLC梯形图代码)-CSDN博客MODBUS通信详细代码编写,请查看下面相关链接,这篇博客主要和大家介绍MODB…...

开源贡献难吗?
本文整理自字节跳动 Flink SQL 技术负责人李本超在 CommunityOverCode Asia 2023 上的 Keynote 演讲,李本超根据自己在开源社区的贡献经历,基于他在贡献开源社区过程中的一些小故事和思考,如何克服困难,在开源社区取得突破&#x…...

seata的TCC模式分析
TCC是 Try- Confirm-Cancel 这3个名词的首字母简称,是一个2阶段提交的变体思路。 Try:对资源的检查和预留; Confirm: 确认对预留资源的消耗,执行业务操作; Cancel:预留资源的释放; TCC的事务…...

常用linux命令【主要用于日志查询,目录切换】
Xshell设置登录 :主机,端口号 用户身份验证:账号/密码登录脚本:等待-[hcuserserver02 ]$ 发送-cd /data/logs/pl-capital-processer-server/$(date “%Y-%m-%d”) 下方-添加按钮/编辑 发送文本,追加 grep --color de…...

Python学习基础笔记七十六——Python装饰器2
装饰器,英文名字decorator。 我们开发Python代码的时候,经常碰到装饰器。 通常被装饰后的函数,会在原来的函数的基础上,增加一些功能。 通常装饰器本事也是一个函数,那么装饰器是怎么装饰另外一个函数的呢?…...

生产环境解决用户登录问题的实践
目录 1 前言2 问题提出3 问题分析和解决4 技术分析和改进5 结语 1 前言 在开发管理软件平台为美术馆时,我们致力于提供一个多系统集成平台,其中包括艺术品管理、志愿者管理和数字资产管理等子系统。为了确保用户享有流畅的体验,我们采用了一…...