OpenGL 原生库4 纹理

news2024/9/20 0:05:30

初始化GLFW:

glfwInit() 初始化GLFW库,这是创建窗口和上下文所必需的第一步。
glfwWindowHint 配置GLFW的上下文版本和配置选项。我们设置了OpenGL版本为3.3,并且使用核心模式。

创建窗口:

glfwCreateWindow 尝试创建一个800x600的窗口。如果失败,则输出错误信息并终止程序。
glfwMakeContextCurrent 将这个窗口的上下文设置为当前线程的上下文。
glfwSetFramebufferSizeCallback 设置窗口大小变化时的回调函数。

加载OpenGL函数指针:

gladLoadGLLoader 使用GLFW提供的glfwGetProcAddress函数来加载OpenGL函数指针。这一步确保我们可以调用所有的OpenGL功能。

构建和编译着色器:

使用自定义的Shader类加载和编译顶点着色器和片段着色器。

设置顶点数据和缓冲:

创建并绑定顶点数组对象(VAO)、顶点缓冲对象(VBO)和元素缓冲对象(EBO)。
将顶点数据和索引数据复制到缓冲中,并配置顶点属性指针。

加载和创建纹理:

创建两个纹理对象,分别从文件中加载图像数据到纹理中,并设置纹理环绕方式和过滤方式。
告知OpenGL每个采样器对应的纹理单元:

使用glUniform1i和自定义Shader类设置每个采样器对应的纹理单元。

渲染循环:

glfwWindowShouldClose 检查窗口是否接收到关闭信号。
processInput 处理输入事件,例如按下ESC键关闭窗口。
glClearColor 和 glClear 设置清屏颜色并清除颜色缓冲。
绑定纹理和VAO,使用着色器程序绘制元素。
glfwSwapBuffers 交换前后缓冲,以显示新的图像。
glfwPollEvents 处理所有的IO事件。

清理资源:

删除VAO、VBO、EBO和着色器程序。
终止GLFW并释放所有资源。

回调函数和输入处理:

processInput 处理键盘输入事件。
framebuffer_size_callback 在窗口大小变化时调整视口。

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>

#include <learnopengl/shader_s.h>

#include <iostream>

// 回调函数,当窗口大小发生变化时调用
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// 设置屏幕宽度和高度
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    // 初始化并配置GLFW
    // ------------------------------
    glfwInit(); // 初始化GLFW库
    // 设置OpenGL版本,这里设置为3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    // 使用核心模式,意味着只使用现代的OpenGL功能
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    // Mac OS X系统需要这行代码来设置OpenGL的向前兼容性
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // 创建一个GLFW窗口
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        // 如果窗口创建失败,输出错误信息并终止程序
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    // 将窗口的上下文设置为当前线程的上下文
    glfwMakeContextCurrent(window);
    // 设置窗口大小变化时的回调函数
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    // 加载所有OpenGL函数指针
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        // 如果GLAD初始化失败,输出错误信息并终止程序
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 构建并编译我们的着色器程序
    // ------------------------------------
    Shader ourShader("4.2.texture.vs", "4.2.texture.fs"); // 自定义Shader类,用于加载和编译着色器

    // 设置顶点数据(和缓冲区),并配置顶点属性
    // ------------------------------------------------------------------
    float vertices[] = {
        // 位置              // 颜色            // 纹理坐标
         0.5f,  0.5f, 0.0f,  1.0f, 0.0f, 0.0f,  1.0f, 1.0f, // 右上
         0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f, // 右下
        -0.5f, -0.5f, 0.0f,  0.0f, 0.0f, 1.0f,  0.0f, 0.0f, // 左下
        -0.5f,  0.5f, 0.0f,  1.0f, 1.0f, 0.0f,  0.0f, 1.0f  // 左上
    };
    unsigned int indices[] = {
        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };
    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // 顶点位置属性
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // 颜色属性
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);
    // 纹理坐标属性
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    // 加载并创建纹理
    // -------------------------
    unsigned int texture1, texture2;
    // 纹理1
    // ---------
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1); 
    // 设置纹理环绕方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// 设置纹理环绕方式为GL_REPEAT(默认环绕方式)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // 设置纹理过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 加载图像,创建纹理并生成mipmap
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true); // 告诉stb_image库在加载图像时翻转y轴
    unsigned char *data = stbi_load(FileSystem::getPath("resources/textures/container.jpg").c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);

    // 纹理2
    // ---------
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // 设置纹理环绕方式
    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_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 加载图像,创建纹理并生成mipmap
    data = stbi_load(FileSystem::getPath("resources/textures/awesomeface.png").c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        // 注意awesomeface.png有透明通道,因此需要将数据类型设置为GL_RGBA
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);

    // 告诉OpenGL每个采样器属于哪个纹理单元(只需要执行一次)
    // -------------------------------------------------------------------------------------------
    ourShader.use(); // 别忘了在设置uniform之前激活着色器
    // 手动设置
    glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);
    // 或者使用着色器类设置
    ourShader.setInt("texture2", 1);

    // 渲染循环
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // 处理输入
        // -----
        processInput(window);

        // 渲染
        // ------
        // 设置清屏颜色
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        // 清除颜色缓冲
        glClear(GL_COLOR_BUFFER_BIT);

        // 绑定纹理
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

        // 渲染容器
        ourShader.use();
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // 交换前后缓冲
        glfwSwapBuffers(window);
        // 处理所有的IO事件(键盘输入、鼠标移动等)
        glfwPollEvents();
    }

    // 可选:在程序结束前删除所有分配的资源
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);

    // 终止GLFW,释放所有资源
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

// 处理所有输入:查询GLFW是否在这一帧中按下/释放了相关键,并作出相应反应
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    // 如果按下了ESC键,设置窗口应关闭
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// 当窗口大小改变时,GLFW会调用这个回调函数
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // 确保视口与新窗口尺寸匹配;注意宽度和高度在Retina显示器上会显著大于指定值
    glViewport(0, 0, width, height);
}

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

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

相关文章

ROS 设置dhcp option 6 多个地址格式

ROS routeOS 手工设置 dhcp 服务 option 6 多个dns 地址格式。字符串方式

erlang学习:Linux常用命令1

Linux的概念 Linux&#xff0c;一般指GNU/Linux&#xff08;单独的Linux内核并不可直接使用&#xff0c;一般搭配GNU套件&#xff0c;故得此称呼&#xff09;&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦&#xff08;Linus…

AI技术好书推荐:《AI系统-原理与架构》

今年1月份在B站发现了一个B站宝藏博主&#xff0c;发布的一系列AI技术类科普视频内容很干&#xff0c;逻辑清晰&#xff0c;很多知识点讲的深入浅出&#xff0c;非常有用&#xff0c;被直接种粉。 后来这一系列的课程内容博主有了出书的计划&#xff0c;机缘巧合有幸参与部分章…

今日所学啊

ArcGIS打不开焦点统计如何解决_arcgis焦点统计打不开-CSDN博客 好吧其实最后焦点统计还是不行&#xff0c;我就去ArcGIS Pro里做焦点统计了哈哈哈哈哈哈哈 visual studio多工程项目管理_visual studio 的模块管理-CSDN博客 1.今天成功#include <QNetworkReply>不画红线…

软件验收测试报告模版分享?专业软件验收测试公司推荐

在现代软件开发中&#xff0c;软件验收测试报告是开发与交付过程中的重要环节&#xff0c;它不仅是对软件产品质量的把关&#xff0c;也是确保客户满意度的关键文档。 在验收测试过程中&#xff0c;测试团队会对软件的各项功能进行全面的测试&#xff0c;识别潜在的问题并进行…

pycv实时目标检测快速实现

使用python_cv实现目标实时检测 python 安装依赖核心代码快速使用实现结果展示enjoy python 安装依赖 opencv_python4.7.0.72 pandas1.5.3 tensorflow2.11.0 tensorflow_hub0.13.0 tensorflow_intel2.11.0 numpy1.23.5核心代码快速使用 # 使用了TensorFlow Hub和OpenCV库来实…

【AI大模型】LLM主流开源大模型介绍

目录 &#x1f354; LLM主流大模型类别 &#x1f354; ChatGLM-6B模型 2.1 训练目标 2.2 模型结构 2.3 模型配置(6B) 2.4 硬件要求 2.5 模型特点 2.6 衍生应用 &#x1f354; LLaMA模型 3.1 训练目标 3.2 模型结构 3.3 模型配置&#xff08;7B&#xff09; 3.4 硬件…

探索RESTful风格的网络请求:构建高效、可维护的API接口【后端 20】

探索RESTful风格的网络请求&#xff1a;构建高效、可维护的API接口 在当今的软件开发领域&#xff0c;RESTful&#xff08;Representational State Transfer&#xff09;风格的网络请求已经成为构建Web服务和API接口的标配。RESTful风格以其简洁、无状态、可缓存以及分层系统等…

YOLOv8的GPU环境搭建方法

首先说明这个环境搭建教程是基于电脑已经安装好CUDA和CUDNN的情况下&#xff0c;去搭建能够正确运行YOLOv8代码的Pytorch的GPU版本。具体安装方法可见&#xff1a;最适合新手入门的CUDA、CUDNN、Pytorch安装教程_cuda安装-CSDN博客 第一步&#xff1a;需要在cmd中创建虚拟环境c…

Mybatis缓存实现

01-一级缓存 演示案例首先创建sql查询语句 在对应接口中声明方法参数是Dept因为sql语句中的参数在Dept pojo类中都有所有声明pojo对象 由于返回的数量不知道是多少条所以用list接收,<>由于返回的是dept类数据所以泛型里传入Dept 一级缓存的介绍如下图 失效情况详细介绍…

【移动端开发】“明日头条APP”

文章目录 1 系统概述1.1研究背景1.2研究意义 2 系统设计2.1 关键技术2.2 系统设计2.2.1 系统功能模块2.2.2 数据库设计 3 系统实现3.1 数据模型3.1.1 NewsURL3.1.2 NewsType3.1.3 NewsInfo 3.2 数据库操作3.2.1 DBOpenHelper3.2.2 DBManager 3.3 适配器类3.3.1 AddItem3.3.2 In…

Python+PyCharm安装(最新)

目录 1.Python和PyCharm简介 2.环境检测 3.Python下载与安装 3.1Python下载 3.2Python安装 3.3python测试 4.PyCharm下载与安装 4.1PyCharm下载 4.2PyCharm安装 4.3PyCharm测试 4.4PyCharm应用 5.注意事项 5.1更新pip 5.2安装库 ​5.3查看已安装的库 6.总结 1.Py…

HAL库中的三种延时函数HAL_Delay、vTaskDelay和vTaskDelayUntil的区别

1、HAL_Delay() 阻塞型延时&#xff0c;实现方式是通过死循环方式实现的&#xff0c;不会释放掉cpu&#xff0c;会造成其他低优先级任务无法执行 2、vTaskDelay() 相对延时函数 void vTaskDelay(TickType_t xTicksToDelay); 相对延时函数:相对延时是指每次延时都是从任务执行…

基于三维地籍的全生命周期“一码管地”

随着国土空间治理现代化的不断推进&#xff0c;如何实现土地资源的高效管理和利用&#xff0c;成为了一个重要课题。今天&#xff0c;我们将探讨一种创新的土地管理模式——基于三维地籍的全生命周期“一码管地”。 一、土地管理面临的挑战 传统的土地管理模式存在信息孤岛、…

《Pure Transformers are Powerful Graph Learners》NIPS2022

摘要 论文展示了标准Transformer模型&#xff0c;无需针对图数据的特定修改&#xff0c;就可以在图学习领域取得有希望的结果&#xff0c;无论是在理论还是实践上。作者提出&#xff0c;通过将图中的所有节点和边视为独立的token&#xff0c;并通过适当的token嵌入增强它们&am…

C++初阶学习第六弹------标准库中的string类

目录 一.标准库中的string类 二.string的常用接口函数 2.1string类对象的构造 2.2 string的容量操作 2.3 string类的访问与遍历 2.4 string类对象的修改 2.5 string类常用的非成员函数 三、总结 一.标准库中的string类 可以简单理解成把string类理解为变长的字符数组&#x…

Linux运维篇-tigervnc工具的使用

目录 简介下载使用clientserver配置文件服务管理 设定密码&#xff08;先切换成对应的用户&#xff09;&#xff1a;配置多用户的VNC tigervnc连接排错一、vnc密码错误二、vncserver端口忘记了三、连接很卡&#xff0c;或者画面没有反应四、服务报错 简介 TigerVNC是VNC的一种…

Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)

题目&#xff1a;*18.29(某个目录下的文件数目) 编写一个程序&#xff0c;提示用户输入一个目录&#xff0c;然后显示该目录下的文件数。 和上一题(18.28)的思路差不多&#xff0c;把找到文件后累加大小到变量变成计数1即可。 Java语言程序设计基础篇_编程练习题*18.28 (非递…

光莆亮相第25届中国国际光博会(CIOE2024)

“光引未来&#xff0c;驱动创新” 2024年9月11-13日&#xff0c;第25届中国国际光电博览会(CIOE2024)在深圳国际会展中心(宝安新馆)隆重开幕。作为国家商务部首批重点展览会&#xff0c;CIOE2024聚焦科研成果转化&#xff0c;推动产学研用深度融合&#xff0c;光电行业全产业…

【海康威视面经】

海康威视面经 Java基础java常用集合 及其优缺点ArrayListVectorLinkedList Jvm调优监控发现问题工具分析问题 &#xff1a;性能调优GC频繁 出现内存泄漏 内存溢出CPU飙升 Synchronized和Volatile的比较反射线程池和new thread利弊高并发 集群 分布式 负载均衡 MySQL调优基础优化…