Cherno OpenGL(14 ~ )

缓冲区布局抽象

首先我们抽象顶点数组的目的是什么?

对我们来说,顶点数组需要做的是将顶点缓冲区与某种布局联系在一起,所以顶点缓冲区就是有数据的缓冲区,它们没有实际的概念比如前三个浮点数是位置,没有类型或者大小之类的概念,它只是实际数据的普通缓冲区。每个字节是什么、这些顶点有多大等等才是顶点数组真正代表的,它应该把缓冲区和实际布局联系在一起。

顶点数组对象是 OpenGL 存储那种状态的方式,那么当我们考虑创建这个接口时,我们需要做的是需要一些东西来创建一个顶点数组。

顶点数组布局 VertexBufferLayout 类

#pragma once#include <vector>
#include <GL/glew.h>
#include "Render.h"struct VertexBufferElement {unsigned int type;unsigned int count;unsigned char normalized;static unsigned int GetSizeOfType(unsigned int type) {switch (type){case GL_FLOAT: return 4;case GL_UNSIGNED_INT: return 4;case GL_UNSIGNED_BYTE: return 1;}ASSERT(false);return 0;}
};class VertexBufferLayout {
private:std::vector<VertexBufferElement> m_Elements;unsigned int m_Stride;
public:VertexBufferLayout():m_Stride(0) {}template<typename T>void Push(unsigned int count) {//static_assert(false);}template<>void Push<float>(unsigned int count) {m_Elements.push_back({GL_FLOAT,count,GL_FALSE});m_Stride += VertexBufferElement::GetSizeOfType(GL_FLOAT) * count;}template<>void Push<unsigned int>(unsigned int count) {m_Elements.push_back({ GL_UNSIGNED_INT,count,GL_FALSE });m_Stride += VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT) * count;}template<>void Push<unsigned char>(unsigned int count) {m_Elements.push_back({ GL_UNSIGNED_BYTE,count,GL_TRUE });m_Stride += VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE) * count;}inline const std::vector<VertexBufferElement>& GetElements()const {return m_Elements;}inline unsigned int GetStride() const {return m_Stride;}
}; 

顶点数组类

.h #pragma once#include "VertexBuffer.h"
#include "VertexBufferLayout.h"class VertexArray {
private:unsigned int m_RenderID;
public:VertexArray();~VertexArray();void AddBuffer(const VertexBuffer& vb,const VertexBufferLayout& layout);void Bind() const;void UnBind() const;
};.cpp#include "VertexArray.h"#include "Render.h"VertexArray::VertexArray() {GLCall(glGenVertexArrays(1, &m_RenderID));GLCall(glBindVertexArray(m_RenderID));
}VertexArray::~VertexArray() {GLCall(glDeleteVertexArrays(1, &m_RenderID));
}void VertexArray::AddBuffer(const VertexBuffer& vb, const VertexBufferLayout& layout) {Bind();vb.Bind();const std::vector<VertexBufferElement>& elements = layout.GetElements();unsigned int offset = 0;for (unsigned int i = 0; i < elements.size();i++) {const auto& element = elements[i];GLCall(glEnableVertexAttribArray(i));GLCall(glVertexAttribPointer(i, element.count, element.type, element.normalized, layout.GetStride(), (const void*)offset));offset += element.count * VertexBufferElement::GetSizeOfType(element.type);}
}void VertexArray::Bind() const {GLCall(glBindVertexArray(m_RenderID));
}
void VertexArray::UnBind() const {GLCall(glBindVertexArray(0));
}

应用 Application 类

#include <GL/glew.h>
#include <GLFW/glfw3.h>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>#include "Render.h"
#include "IndexBuffer.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
#include "VertexArray.h"struct ShaderProgramSource {std::string VertexSource;std::string FragmentSource;
};//从文件中将着色器代码读取出来
static ShaderProgramSource ParseShader(const std::string& filepath) {std::ifstream stream(filepath);enum class ShaderType {NONE = -1, VERTEX = 0, FRAGMENT = 1};std::string line;std::stringstream ss[2];ShaderType type = ShaderType::NONE;while (getline(stream, line)) {if (line.find("#shader") != std::string::npos) {if (line.find("vertex") != std::string::npos) {type = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos) {type = ShaderType::FRAGMENT;}}else {ss[(int)type] << line << '\n';}}return { ss[0].str(),ss[1].str() };
}static unsigned int CompileShader(unsigned int type, const std::string& source) {unsigned int id = glCreateShader(type);const char* src = source.c_str();glShaderSource(id, 1, &src, nullptr);glCompileShader(id); //Syntax error handlingint result;glGetShaderiv(id, GL_COMPILE_STATUS, &result);if (result == GL_FALSE) {  //编译失败 获取错误信息int length;glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);char* message = (char*)alloca(length * sizeof(char));glGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile" << (type == GL_VERTEX_SHADER ? "vertexShader" : "fragmentShader ") << " shader!" << std::endl;std::cout << message << std::endl;glDeleteShader(id);return 0;}return id;
}//我们向OpenGL提供我们实际的着色器源代码,我的着色器文本。我们想让OpenGL编译那个程序,将这两个链接到一个
//独立的着色器程序,然后给我们一些那个着色器返回的唯一标识符,我们就可以绑定着色器并使用
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {unsigned int program = glCreateProgram();unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);//将这两个着色器附加到我们的程序上glAttachShader(program, vs);glAttachShader(program, fs);//链接程序glLinkProgram(program);glValidateProgram(program);//删除一些无用的中间文件glDeleteShader(vs);glDeleteShader(fs);return program;
}int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);  //指定opengl版本,3glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);  //指定opengl次要版本 0.3  即3.3 //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); //兼容版本glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 核心版本/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {  //should after MakeContextCurrent std::cout << "Error" << std::endl;}std::cout << glGetString(GL_VERSION) << std::endl;{float positions[] = {-0.5f, -0.5f, //00.5f, -0.5f, //10.5f, 0.5f, //2-0.5f,0.5f, //3};unsigned int indices[] = {0,1,2,2,3,0};VertexArray va;// 顶点缓冲区VertexBuffer vb(positions, 8 * sizeof(float));VertexBufferLayout layout;layout.Push<float>((unsigned int)2);va.AddBuffer(vb,layout);//索引缓冲区IndexBuffer ib(indices, 6);ShaderProgramSource source = ParseShader("res/Shaders/Basic.shader");unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);//绑定着色器glUseProgram(shader);int location = glGetUniformLocation(shader, "u_Color");ASSERT(location != -1);//将所有绑定解绑va.UnBind();glUseProgram(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);float r = 0.0f;float increment = 0.05f;/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);GLClearError();//为了正确绘制图形,重新进行绑定glUseProgram(shader);//glBindBuffer(GL_ARRAY_BUFFER, buffer);//glEnableVertexAttribArray(0);//glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, 0);va.Bind();ib.Bind();glUniform4f(location, r, 0.0f, 1.0f, 1.0f);//Draw callGLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));if (r > 1.0f) {increment = -0.0001f;}else if (r <= 0.0f) {increment = 0.0001f;}r += increment;/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}//删除着色器glDeleteProgram(shader);
}glfwTerminate();return 0;
}

着色器抽象

着色器需要什么?

第一步首先我们希望能够传递一个文件或者字符串,把它作为着色器来编译;第二步我们希望能够绑定和解绑着色器;第三步则是我们需要能够设置着色器中各种不同的统一变量,这可能就是我们现在正在研究的东西

参考博文:Cherno OpenGL 教程 | Fl0w3r

视频地址:S13.抽象OpenGL成类_哔哩哔哩_bilibili

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

第5章-总体设计 5.2 需求转化为规格

5.2 需求转化为规格 1.框式产品&#xff08;1&#xff09;业务规格&#xff0c;这需要满足客户期望、有市场竞争力、颗粒度最合理。&#xff08;2&#xff09;整框规格&#xff0c;包括电源、功耗、散热、可靠性的规格&#xff0c;要保证整款满足环境应用要求。&#xff08;3&a…

kali上安装docker,并且生成centos7容器和创建apache容器后台运行

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明

4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明 文章目录 4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明前言1. Ribbon 介绍1.1 LB(Load Balance 负载均衡) 2. Ribbon 原理2.2 Ribbon 机制 3. Spring Cloud Ribbon 实现负载均衡算法-应用实例4. 总结&#x…

约克VRF中央空调新天氟地水/天氟热水,做冬日生活的温暖守护者

随着冬季的悄然降临,现代人对居家环境的舒适性要求愈发提升,如何在寒冷的季节里营造一个温暖、静谧且健康的居住空间,成为了时下关注的焦点。面对冬日空气干燥、寒气侵袭的挑战,约克VRF中央空调凭借其氟系统和水系统的跨界融合,为家庭带来了纵享四季的恣意体验,让温暖与舒适触手…

计算机提示mfc140u.dll丢失的五种解决方法,了解mfc140u.dll错误的几种修复方法

当你尝试打开某些程序时&#xff0c;突然出现错误提示&#xff0c;告知你系统缺少 mfc140u.dll 文件&#xff0c;这可能让你感到困惑和无助。mfc140u.dll 是 Microsoft Foundation Class (MFC) 库的一部分&#xff0c;对于运行很多由 Visual Studio 2015 使用 MFC 开发的应用程…

【SSL-RL】自监督强化学习: 好奇心驱动探索 (CDE)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

Windows系统 ElasticSearch,Kibana安装

目录 1.wins安装ElasticSearch2.将 elasticsearch 以服务的方式安装3. 在系统环境变量 Path 中添加如下路径4.启动点击即可5.双击 elasticsearch.bat 启动 elasticsearch 服务6.启动后第一次会显示一些配置信息,包括默认的用户密码 先记住 记不住的话可以重置密码7.验证安装结果…

《Probing the 3D Awareness of Visual Foundation Models》论文解析——单图像表面重建

一、论文简介 论文讨论了大规模预训练产生的视觉基础模型在处理任意图像时的强大能力&#xff0c;这些模型不仅能够完成训练任务&#xff0c;其中间表示还对其他视觉任务&#xff08;如检测和分割&#xff09;有用。研究者们提出了一个问题&#xff1a;这些模型是否能够表示物体…

P3-4.【结构化程序设计】第四节——知识要点:break、continue和goto辅助循环设计语句

知识要点&#xff1a;break、continue和goto辅助循环设计语句 视频&#xff1a; P3-4.1.【结构化程序设计】第四节——知识要点&#xff1a;break、continue和goto辅助循环设计语句 P3-4.2.【结构化程序设计】第四节——知识要点&#xff1a;break、continue和goto辅助循环设计…

灵神DAY3 KMP算法

具体解释&#xff1a; 1. 真前缀和真后缀的定义 前缀&#xff1a;字符串的起始部分。例如&#xff0c;字符串 s "aabcaa" 的前缀是 ""、"a"、"aa"、"aab"、"aabc"、"aabca"、"aabcaa"。 …

MySQL5.7.37安装配置

1.下载MySQL软件包并解压 2.配置环境变量 3.新建my.ini文件并输入信息 [mysqld] #端口号 port 3306 #mysql-5.7.27-winx64的路径 basedirC:\mysql-5.7.37\mysql-5.7.37-winx64 #mysql-5.7.27-winx64的路径\data datadirC:\mysql-5.7.37\mysql-5.7.37-winx64\data #最大连接数…

基于单片机的手持金属探测仪设计

本设计以STM32F103C8T6单片机为核心&#xff0c;通过金属线圈感应器来判断是否存在金属&#xff0c;控制OLED显示屏显示金属探测仪的灵敏度和参考值&#xff0c;通过电源模块将220V转化为3.3V对单片机进行供电&#xff0c;还可以通过按键对金属探测仪的灵敏度进行设置&#xff…

P1197 星球大战(并查集+逆向思维)

这是今天写的比较有价值的一道题&#xff0c;晚上写了大概一个多小时&#xff0c;主要还是在debug&#xff0c;出得很妙&#xff0c;好题&#x1f44d; P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态 思路&#xff1a;如果我们按照顺序一个一个的去计算毁灭一个星…

深度学习驱动的蛋白质设计技术与前沿实践-从基础到尖端应用

RoseTTAFold&#xff0c;作为David Baker教授团队早期开发的蛋白质结构预测工具&#xff0c;在学术界与工业界广受认可。然而&#xff0c;随着时间推移&#xff0c;仅局限于预测已知结构的蛋白质并不能满足生物医药和生物工程领域对创新设计的需求。这促使David Baker教授团队继…

Linux 进程信号初识

目录 0.前言 1.什么是信号 1.1生活中的信号 1.2 OS中的信号 2.认识信号 2.1信号概念 2.2查看信号 2.3 signal函数 2.4代码示例 3. 信号处理方式 3.1 忽略信号 3.2 默认处理 3.3 自定义处理 4.小结 &#xff08;图像由AI生成&#xff09; 0.前言 在之前的学习中&#xff0c;我…

SpringBoot(二十五)SpringBoot集成JRebel实现热更新

今天来安装一个IDEA代码热更新的插件,一个神器。 我们之前也为IDEA配置了热更新,使用的是spring-boot-devtools插件。具体请移步《SpringBoot(一)创建项目及配置IDEA热更新》 上边这个热更新对于单模块项目是没有问题的,但是对于多模块项目可能就无能无能为力了,而且,随…

MATLAB中的绘图技巧

MATLAB作为一种强大的科学计算软件&#xff0c;不仅可以进行数据分析和模拟&#xff0c;还具有出色的绘图功能。本文介绍若干在MATLAB中绘图的技巧和方法&#xff0c;帮助使用者更好地呈现数据和结果 文章目录 基本绘图函数高级绘图技巧三维绘图动态绘图绘图工具结语 基本绘图函…

java八股-AQS,Reentrantlock

什么是AQS&#xff1f; 难度&#xff1a;★★★☆☆ 考频&#xff1a;★★★☆☆ 注意这个队列是双向队列&#xff0c;每次有线程释放锁了之后&#xff0c;会有下一个线程来&#xff0c;以及队列头元素&#xff0c;如果设置的是公平锁&#xff0c;那么是等了很久的头元素先获…

python——模块 迭代器 正则

一、python模块 先创建一个 .py 文件&#xff0c;这个文件就称之为 一个模块 Module。 使用模块的优点&#xff1a; 模块化编程&#xff0c;多文件编程 1.2 模块的使用 1.2.1 import语句 想要B.py文件中&#xff0c;使用A.py文件&#xff0c;只需要在B.py文件中使用关键字…

STL之mapset|AVL树

STL之map&set|AVL树 set&map搜索二叉树实现代码 set的使用map的使用set&map的模拟实现&#xff08;见红黑树篇&#xff09; AVL树AVL树的模拟实现 set&map 前言&#xff1a;stl库中set和map的底层都是红黑树&#xff0c;一种平衡搜索二叉树&#xff0c;是我下…