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

C++自研3D教程OPENGL版本---动态批处理的基本实现

又开始找工作了,借机休息出去旅行两个月,顺便利用这段时间整理下以前写的东西。
以下是一个简单的动态批处理实现:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>// 顶点结构体
struct Vertex {float x, y, z; // 位置float r, g, b; // 颜色
};// 动态批处理类
class DynamicBatch {
public:DynamicBatch() {// 初始化 VAO 和 VBOglGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);// 设置顶点属性指针glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, x));glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, r));glEnableVertexAttribArray(1);glBindVertexArray(0);}~DynamicBatch() {glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);}// 添加顶点数据void AddVertex(const Vertex& vertex) {vertices.push_back(vertex);}// 更新顶点缓冲区void UpdateBuffer() {glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_DYNAMIC_DRAW);}// 渲染批处理void Render() {glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, vertices.size());glBindVertexArray(0);}// 清空顶点数据void Clear() {vertices.clear();}private:GLuint VAO, VBO; // 顶点数组对象和顶点缓冲区对象std::vector<Vertex> vertices; // 顶点数据
};

// 顶点着色器

const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
out vec3 ourColor;
void main() {gl_Position = vec4(aPos, 1.0);ourColor = aColor;
}
)";// 片段着色器
const char* fragmentShaderSource = R"(
#version 330 core
in vec3 ourColor;
out vec4 FragColor;
void main() {FragColor = vec4(ourColor, 1.0);
}
)";
// 编译着色器
GLuint CompileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "Shader compilation failed: " << infoLog << std::endl;}return shader;
}// 链接着色器程序
GLuint CreateShaderProgram(const char* vertexSource, const char* fragmentSource) {GLuint vertexShader = CompileShader(GL_VERTEX_SHADER, vertexSource);GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentSource);GLuint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);GLint success;glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);std::cerr << "Shader program linking failed: " << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return shaderProgram;
}int main() {// 初始化 GLFWif (!glfwInit()) {std::cerr << "Failed to initialize GLFW" << std::endl;return -1;}// 创建窗口GLFWwindow* window = glfwCreateWindow(800, 600, "Dynamic Batching Example", nullptr, nullptr);if (!window) {std::cerr << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);// 初始化 GLEWif (glewInit() != GLEW_OK) {std::cerr << "Failed to initialize GLEW" << std::endl;return -1;}// 创建着色器程序GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);// 创建动态批处理对象DynamicBatch batch;// 主循环while (!glfwWindowShouldClose(window)) {glClear(GL_COLOR_BUFFER_BIT);// 添加顶点数据batch.Clear();batch.AddVertex({-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f});batch.AddVertex({0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f});batch.AddVertex({0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f});// 更新缓冲区并渲染batch.UpdateBuffer();glUseProgram(shaderProgram);batch.Render();// 交换缓冲区glfwSwapBuffers(window);glfwPollEvents();}// 清理glDeleteProgram(shaderProgram);glfwTerminate();return 0;
}

代码说明
DynamicBatch 类:

负责管理顶点数据、更新顶点缓冲区和渲染。使用 std::vector 存储动态顶点数据。
通过 glBufferData 将顶点数据上传到 GPU。
顶点和片段着色器:简单的着色器,用于渲染带颜色的三角形。
主循环:每一帧清空批处理数据,添加新的顶点数据,更新缓冲区并渲染。
动态更新:使用 GL_DYNAMIC_DRAW 标志更新顶点缓冲区,适用于频繁变化的顶点数据。

运行结果
运行程序后,你会看到一个彩色的三角形。每一帧都会动态更新顶点数据并渲染。

优化建议
减少内存分配:
如果顶点数据频繁变化,可以预先分配足够的内存,避免频繁调用 glBufferData。
使用实例化渲染:
如果需要渲染大量相同对象,可以使用实例化渲染(Instanced Rendering)进一步优化性能。
多线程更新:
在多线程环境中,可以将顶点数据的更新和渲染分离到不同的线程中。
通过动态批处理,你可以有效地减少绘制调用,提高渲染性能,特别是在需要渲染大量小对象的场景中。

相关文章:

C++自研3D教程OPENGL版本---动态批处理的基本实现

又开始找工作了&#xff0c;借机休息出去旅行两个月&#xff0c;顺便利用这段时间整理下以前写的东西。 以下是一个简单的动态批处理实现&#xff1a; #include <GL/glew.h> #include <GLFW/glfw3.h> #include <iostream> #include <vector>// 顶点结…...

docker /var/lib/docker/overlay2目录把磁盘空间占满问题

1、查看服务器磁盘空间 df -h果然100%了,docker系统文件把磁盘空间占满了。 2、进入overlay2目录&#xff0c;查找那个容器工作目录占用最高 cd /var/lib/docker/overlay2du -h --max-depth1详见下图 好家伙占用110G&#xff01;复制目录名称2c3c48ccac533c5d4a366d45a19bb9…...

SOA(面向服务架构)全面解析

1. 引言 什么是SOA&#xff08;面向服务架构&#xff09; SOA&#xff08;Service-Oriented Architecture&#xff0c;面向服务架构&#xff09;是一种将应用程序功能以“服务”的形式进行模块化设计的架构风格。这些服务是独立的功能模块&#xff0c;它们通过定义明确的接口…...

华为交换机堆叠配置

一、CSS堆叠集群配置&#xff08;框式交换机&#xff09; 1、通过集群卡连接方式组建集群 [SwitchA] set css mode css-card \\配置集群卡连接方式 [SwitchA] set css id 1 \\配置成员交换机的集群ID(缺省值为1) [SwitchA] set css priority 100 \\配…...

蓝桥杯备赛——进制转化相关问题

目录 一、基础概念 二、问题研究&#xff08;1&#xff09; 代码解读&#xff1a; 1. transfer 函数 代码功能概述 详细步骤 2. main 函数 代码功能概述 详细步骤 三、运用递归解决 &#xff08;一&#xff09; 代码如下&#xff1a; 代码解读&#xff1a; &#…...

Nginx配置 ngx_http_proxy_connect_module 模块及安装

1、配置完互联网yum源后,安装相关依赖软件包 [root@server soft]# yum install -y patch pcre pcre-devel make gcc gcc-c++ openssl openssh [root@server soft]# yum install openssl* 2、解压缩软件,加载模块 [root@server soft]# ls nginx-1.20.2 nginx-1.20.2.tar.gz …...

WebSocket推送数据快,条数多导致前端卡顿问题解决

WebSocket推送数据快&#xff0c;条数多导致前端卡顿问题解决 前言方案优化消息频率使用高效的数据格式Protobuf 和 MessagePack的对比 启用压缩前端性能优化 WebSocket使用注意事项连接管理处理断开连接负载均衡监控和维护日志记录定期维护安全最佳实践限流 最后 前言 在项目…...

网络爬虫技术如何影响网络安全的

随着网络的发展和网络爬虫技术的普及&#xff0c;一些人收集某些需要的信息&#xff0c;会使用网络爬虫进行数据抓取。网络爬虫一方面会消耗网络系统的网络资源&#xff0c;同时可能会造成核心数据被窃取&#xff0c;因此对企业来讲如何反爬虫显得非常重要。 一、什么是网络爬…...

基于蒙特卡洛思想生成电动汽车充电负荷曲线

本程序基于蒙特卡洛思想生成电动汽车充电负荷曲线&#xff0c;利用第十一届电工杯所提供的数据&#xff08;充电开始时间&#xff0c;充电电量&#xff0c;充电功率&#xff09;得到一万台电动汽车充电负荷曲线。蒙特卡洛只是解决问题的一种思想&#xff0c;本程序可为其他利用…...

Redis深入学习

目录 Redis是什么&#xff1f; Redis使用场景 Redis线程模型 Redis执行命令是单线程的为什么还这么快&#xff1f; Redis持久化 Redis 事务 Key 过期策略 Redis 和 mysql 如何保证数据一致&#xff1f; 缓存穿透 缓存击穿 缓存雪崩 Redis是什么&#xff1f; redis是一…...

kamailio中路由模块汇总

功能模块描述请求路由 (request_route)主要处理进入的SIP请求&#xff0c;包含初步检查、NAT检测、CANCEL请求处理、重传处理等。处理通过REQINIT、NATDETECT、RELAY等子模块的调用。CANCEL处理对CANCEL请求进行处理&#xff0c;包括更新对话状态并检查事务。如果事务检查通过&…...

EasyExcel 导出合并层级单元格

EasyExcel 导出合并层级单元格 一、案例 案例一 1.相同订单号单元格进行合并 合并结果 案例二 1.相同订单号的单元格进行合并2.相同订单号的总数和总金额进行合并 合并结果 案例三 1.相同订单号的单元格进行合并2.相同订单号的商品分类进行合并3.相同订单号的总数和总金额…...

青少年编程与数学 02-009 Django 5 Web 编程 01课题、概要

青少年编程与数学 02-009 Django 5 Web 编程 01课题、概要 一、Django 5Django 5 的主要特性包括&#xff1a; 二、MVT模式三、官方网站四、内置功能数据库 ORM&#xff08;对象关系映射&#xff09;用户认证和授权表单处理模板引擎URL 路由缓存框架国际化和本地化安全性功能管…...

Oracle认证大师(OCM)学习计划书

Oracle认证大师&#xff08;OCM&#xff09;学习计划书 一、学习目标 Oracle Certified Master&#xff08;OCM&#xff09;是Oracle官方认证体系中的最高级别认证&#xff0c;要求考生具备扎实的数据库管理技能、丰富的实战经验以及解决复杂问题的能力。本计划旨在通过系统化的…...

2.7学习

crypto buu-还原大师 仔细阅读题目&#xff0c;这里有一段字符串&#xff0c;但是其中有四个大写字母被替换成了‘&#xff1f;’&#xff0c;那么我们写脚本&#xff1a;首先将四个问号均换成26个大写字母并且组成不同的组合&#xff0c; 所以有四个循环让四个问号都遍历26个…...

oracle ORA-27054报错处理

现象 在oracle执行expdp&#xff0c;rman备份&#xff0c;xtts的时候,由于没有足够的本地空间&#xff0c;只能使用到NFS的文件系统但有时候会出现如下报错 ORA-27054: NFS file system where the file is created or resides is not mounted with correct options根据提示信…...

核显是什么

核显&#xff08;Integrated Graphics&#xff0c;集成显卡&#xff09;是指集成在中央处理器&#xff08;CPU&#xff09;或者主板上的显卡。与独立显卡不同&#xff0c;核显不需要额外的显卡硬件&#xff0c;而是直接使用系统内存&#xff08;RAM&#xff09;和处理器的资源来…...

使用LLaMA Factory踩坑记录

前置条件&#xff1a;电脑显卡RTX 4080 问题&#xff1a;LLaMA-Factory在运行的时候&#xff0c;弹出未检测到CUDA的报错信息 结论&#xff1a;出现了以上的报错&#xff0c;主要可以归结于以下两个方面&#xff1a; 1、没有安装GPU版本的pytorch&#xff0c;下载的是CPU版本…...

在qtcreator中添加片段,提高开发效率。

文件名&#xff1a;text.xml <?xml version"1.0" encoding"utf-8"?> <snippets><!-- 版权声明 --><snippet group"Text" trigger"copyright" id"comment_copyright">/*!* file %{CurrentDocum…...

redis的数据结构介绍(string

redis是键值数据库&#xff0c;key一般是string类型&#xff0c;value的类型很多 string&#xff0c;hash&#xff0c;list&#xff0c;set&#xff0c;sortedset&#xff0c;geo&#xff0c;bitmap&#xff0c;hyperlog redis常用通用命令&#xff1a; keys&#xff1a; …...

ASP.NET Core JWT Version

目录 JWT缺点 方案 实现 Program.cs IdentityHelper.cs Controller NotCheckJWTVersionAttribute.cs JWTVersionCheckkFilter.cs 优化 JWT缺点 到期前&#xff0c;令牌无法被提前撤回。什么情况下需要撤回&#xff1f;用户被删除了、禁用了&#xff1b;令牌被盗用了&…...

电路研究9.3——合宙Air780EP中的AT开发指南(含TCP 示例)

根据合宙的AT研发推荐&#xff0c; AT指令基本上也简单看完了&#xff0c;这里开始转到AT的开发了。 AT 命令采用标准串口进行数据收发&#xff0c;将以前复杂的设备通讯方式转换成简单的串口编程&#xff0c; 大大简化了产品的硬件设计和软件开发成本&#xff0c;这使得几乎所…...

Reqable使用实践

一、背景 日常开发中&#xff0c;难免要抓取请求数据&#xff0c;查看接口数据&#xff0c;从而更好定位问题&#xff0c;基于这个原因&#xff0c;查找了一些抓包工具&#xff0c;例如&#xff1a; HttpCanary、 Steam 、Fiddler等&#xff0c;不是要钱&#xff0c;就是只对苹…...

【蓝桥杯嵌入式】2_LED

全部代码网盘自取 链接&#xff1a;https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码&#xff1a;3ii2 1、电路图 74HC573是八位锁存器&#xff0c;当控制端LE脚为高电平时&#xff0c;芯片“导通”&#xff0c;LE为低电平时芯片“截止”即将输出状态“锁存”…...

Flink 调用海豚调度器 SQL 脚本实现1份SQL流批一体化的方案和可运行的代码实例

目录 一、流批一体化概述 二、Flink 与海豚调度器结合实现流批一体化的好处 2.1 代码复用性增强 2.2 开发和维护成本降低 2.3 数据一致性保证 2.4 提高系统的灵活性和可扩展性 三、实现思路步骤 3.1 环境准备 3.2 编写 SQL 脚本并上传到海豚调度器 3.3 实现资源下载功…...

B树详解及其C语言实现

目录 一、B树的基本原理 二、B树操作过程图形化演示 三、B树的应用场景 四、C语言实现B树及示例 五、代码执行结果说明 六、应用实例&#xff1a;文件系统目录索引 七、总结 一、B树的基本原理 B树&#xff08;B-Tree&#xff09; 是一种自平衡的树数据结构&#xff0c;…...

【Go语言快速上手】第二部分:Go语言进阶

文章目录 并发编程goroutine&#xff1a;创建和调度 goroutinechannel&#xff1a;无缓冲 channel、有缓冲 channel、select 语句无缓冲 channel有缓冲 channelselect 语句 sync 包&#xff1a;Mutex、RWMutex、WaitGroup 等同步原语Mutex&#xff1a;互斥锁RWMutex&#xff1a…...

ARM64 Linux 内核学习指南:从基础到实践

前言 ARM64 作为当今主流的处理器架构&#xff0c;被广泛应用于移动设备、嵌入式系统和服务器领域。学习 ARM64 在 Linux 内核中的实现&#xff0c;不仅有助于深入理解操作系统底层机制&#xff0c;还能提升在内核开发、驱动编写、虚拟化等领域的专业能力。 本指南面向对 Lin…...

零基础都可以本地部署Deepseek R1

文章目录 一、硬件配置需求二、详细部署步骤1. 安装 Ollama 工具2. 部署 DeepSeek-R1 模型3. API使用4. 配置图形化交互界面&#xff08;可选&#xff09;5. 使用与注意事项 一、硬件配置需求 不同版本的 DeepSeek-R1 模型参数量不同&#xff0c;对硬件资源的要求也不尽相同。…...

掌握Spring @SessionAttribute:跨请求数据共享的艺术

SessionAttribute注解在Spring中的作用&#xff0c;就像是一个“数据中转站”。 在Web应用中&#xff0c;我们经常需要在多个请求之间共享数据。比如&#xff0c;用户登录后&#xff0c;我们需要在多个页面或请求中保持用户的登录状态。这时&#xff0c;SessionAttribute注解就…...