图片纹理贴图

/*
* 当需要给图形赋予真实颜色的时候,不太可能为没一个顶点指定一个颜色,通常会采用纹理贴图
* 每个顶点关联一个纹理坐标 (Texture Coordinate) 其它片段上进行片段插值
* 
*/



#include <iostream>
#define STBI_NO_SIMD
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"


#include <glad/glad.h>   // 把这个头文件放在最上面
#include <GLFW/glfw3.h>
#include <string>
#include <fstream>
#include <sstream>


#include "glm/glm.hpp"



class MyShader {
public:
    unsigned int ID;	// 着色器程序 ID


    // 构造函数读取并构建 shader
    MyShader(const char* vertexPath, const char* fragmentPath);

    // 使用激活 Shader
    void use();

    // 设置 uniform 的工具函数
    void setBool(const std::string& name, bool value) const;
    void setInt(const std::string& name, int value) const;
    void setFloat(const std::string& name, float value) const;
    void setVec4(const std::string& name, const glm::vec4& value) const;

};


MyShader::MyShader(const char* vertexPath, const char* fragmentPath)
{
    // 从文件加载 shader 的源码
    // 1.0 从文件路径加载顶点 / 片段源代码
    std::string vertexCode, fragmentCode;
    std::ifstream vShaderFile, fShaderFile;

    // 确保 ifstream 对象可以引发异常
    vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

    try
    {
        // 打开文件
        vShaderFile.open(vertexPath);
        fShaderFile.open(fragmentPath);

        std::stringstream vShaderStream, fShaderStream;
        // 将文件的缓冲区内容读入流
        vShaderStream << vShaderFile.rdbuf();
        fShaderStream << fShaderFile.rdbuf();

        // 关闭文件处理程序
        vShaderFile.close();
        fShaderFile.close();

        // 将流转换为字符串
        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();

    }
    catch (const std::ifstream::failure e)
    {
        std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;
    }
    const char* vShaderCode = vertexCode.c_str();
    const char* fShaderCode = fragmentCode.c_str();

    // 编译着色器

    unsigned int vertexShader, fragmentShader;
    int success;
    char infoLog[512];

    // 顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderCode, nullptr);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

    if (!success)	// 打印错误提示信息
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    //片元着色器
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fShaderCode, nullptr);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }


    //着色器程序
    ID = glCreateProgram();
    glAttachShader(ID, vertexShader);
    glAttachShader(ID, fragmentShader);
    glLinkProgram(ID);
    glGetProgramiv(ID, GL_LINK_STATUS, &success);
    if (!success)
    {
        glGetProgramInfoLog(ID, 512, nullptr, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    //删除着色器
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

void MyShader::use()
{
    glUseProgram(ID);
}


void MyShader::setBool(const std::string& name, bool value) const
{
    glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}

void MyShader::setInt(const std::string& name, int value) const
{
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}


void MyShader::setFloat(const std::string& name, float value) const
{
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}


void MyShader::setVec4(const std::string& name, const glm::vec4& value) const
{
    glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}



//响应键盘输入事件
//ESC推出窗口
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {
        glfwSetWindowShouldClose(window, true);
    }
}

//当用户改变窗口的大小的时候,视口也应该被调整。
//对窗口注册一个回调函数(Callback Function),它会在每次窗口大小被调整的时候被调用
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    //glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
    glViewport(0, 0, width, height);
}




int main()
{
    float vertices[] = {
        // 位置             // 颜色	         // 纹理坐标 
        0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,	// 右上
        0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,	// 右下
       -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,	// 左下
       -0.5f,  0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f	// 左上

    };

    unsigned int indices[] = {
            0, 1, 3,
            1, 2, 3,
    };


    /*******************************************定义常量************************************************/
    //设置窗口的宽和高
    const unsigned int SCR_WIDTH = 800;
    const unsigned int SCR_HEIGHT = 600;
    /*******************************************函数***************************************************/

     //初始化GLFW
    glfwInit();
    // 初始化GLFW
    if (!glfwInit())
    {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    //声明版本与核心
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); //主版本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); //次版本号
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //创建窗口并设置其大小,名称,与检测是否创建成功
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", nullptr, nullptr);
    if (window == nullptr)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    //创建完毕之后,需要让当前窗口的环境在当前线程上成为当前环境,就是接下来的画图都会画在我们刚刚创建的窗口上
    glfwMakeContextCurrent(window);
    //告诉GLFW我们希望每当窗口调整大小的时候调用这个函数
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);


    //glad寻找opengl的函数地址,调用opengl的函数前需要初始化glad
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 创建一个 shader 的类
    MyShader shader("shader/shader.vs", "shader/shader.fs");

    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);         //绑定VAO对象

    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);



    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, 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);


    // 绑定 EBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


    //链接顶点属性,设置顶点属性指针

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    //以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的。
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);


    // 读一张纹理图像

    int width, height, channels;
    unsigned char* data = stbi_load("lena.jpg", &width, &height, &channels, 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);



    //glfwWindowShouldClose()检查窗口是否需要关闭。如果是,游戏循环就结束了,接下来我们将会清理资源,结束程序
    while (!glfwWindowShouldClose(window))
    {
        //响应键盘输入
        processInput(window);

        //设置清除颜色
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        //清除当前窗口,把颜色设置为清除颜色
        glClear(GL_COLOR_BUFFER_BIT);

        shader.use();		// 选择流水线

        // 设置unifor 值
        float timeValue = glfwGetTime();
        float greenValue = sin(timeValue) / 2.0f + 0.5f;


        glm::vec4 color = glm::vec4(0.0f, greenValue, 0.0f, 1.0f);
        shader.setVec4("ourColor", color);


        //绑定VAO
        glBindVertexArray(VAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);


        //glDrawArrays(GL_TRIANGLES, 0, 3);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        //线框绘制
        //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        //交换颜色缓冲 
        glfwSwapBuffers(window);
        //处理事件
        glfwPollEvents();

    }

    //释放前面所申请的资源
    glfwTerminate();
     清理资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shader.ID);



 

    return 0;

}


在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Docker基础

文章目录 安装使用帮助启动命令镜像命令容器命令 安装 # 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine # 设置存储库 sudo yum install -y yum-utils …

数据结构与算法(十)深度优先搜索与广度优先搜索

广度优先搜索 广度优先搜索&#xff1a;从一个顶点出发&#xff08;由开始时顶点创造顺序优先决定&#xff09;&#xff0c;访问所有没有被访问过的临节点。然后在从被访问过的节点出发&#xff0c;重复之前的操作 如下为一个图 从1出发&#xff0c;先后访问2 3&#xff0c;之后…

VMware复制粘贴共享文件夹

win和虚拟机之间&#xff0c;无法复制粘贴&#xff0c;共享文件夹的解决方案。 安装VMware tools 1&#xff0c;先检查虚拟机设置部分。共享文件夹已启用。复制粘贴已启用。 2&#xff0c;安装tools.选择重新安装VMware tools. (此图片为安装过的截图) 成功后会显示如图。…

C++的一些书籍整理(个人学习)

UNIX环境高级编程&#xff08;第三版&#xff09; UNXI网络编程卷1 网络编程的笔记 收藏 我会了 一堆书 这个仓 数据库连接池原理介绍常用连接池介绍

计算机体系结构期末复习流程大纲

1.存储器和cache 存储器的容量、速度与价格之间的要求是相互矛盾的&#xff0c;速度越快&#xff0c;没bit位价格越高&#xff0c;容量越大&#xff0c;速度越慢&#xff0c;目前主存一般有DRAM构成。 处理器CPU访问存储器的指标&#xff1a; 延迟时间&#xff08;Latency&am…

LeetCode刷题--- 下降路径最小和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 ​​​​​​http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述动…

Oracle文件自动“减肥”记

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

欧拉图及其应用

什么是欧拉图 提到欧拉图就要谈到哥尼斯堡七桥问题&#xff0c;最初有这样的一个问题的&#xff1a;18世纪中叶&#xff0c;东普鲁士哥尼斯堡城有一条贯穿全城的普雷格尔河&#xff0c;河中有两个岛&#xff0c;通过七座桥彼此相连&#xff0c;如下图所示 问题是这样的&…

UnitTestreport之UnitTest用例失败重运行机制

前言 很多小伙伴一直在诟病unittest&#xff0c;说unittest相对pytest来说太鸡肋了&#xff0c;pytest中提供了很多高级功能unittest中都没有。在这里还是想为unittest打抱不平一下&#xff0c;unittest是由python官方维护的官方库&#xff0c;官方库都是比较轻量级的&#xf…

以太坊开发者会议回顾:坎昆升级、硬分叉与布拉格

作者&#xff1a;Christine Kim Galaxy研究副总裁 编译&#xff1a;秦晋 碳链价值 2024年1月4日&#xff0c;以太坊开发人员齐聚Zoom for All Core Developers Execution (ACDE) Call #178 上。ACDE电话会议通常由以太坊基金会协议负责人Tim Beiko主持&#xff0c;是一个开发人…

【STM32】STM32学习笔记-串口发送和接收(27)

00. 目录 文章目录 00. 目录01. 串口简介02. 串口相关API2.1 USART_Init2.2 USART_InitTypeDef2.3 USART_Cmd2.4 USART_SendData2.5 USART_ReceiveData 03. 串口发送接线图04. USB转串口模块05. 串口发送程序示例06. 串口发送支持printf07. 串口发送支持printf_v208. 串口发送和…

5分钟彻底搞懂什么是token

大家好啊&#xff0c;我是董董灿。 几年前在一次工作中&#xff0c;第一次接触到自然语言处理模型 BERT。 当时在评估这个模型的性能时&#xff0c;领导说这个模型的性能需要达到了 200 token 每秒&#xff0c;虽然知道这是一个性能指标&#xff0c;但是对 token 这个概念却不…

聚道云软件连接器助力某餐饮管理有限公司实现人力资源信息自动化

客户介绍&#xff1a; 某餐饮管理有限公司是一家集餐饮连锁、餐饮管理、餐饮咨询等业务于一体的综合性餐饮企业。公司业务遍布全国多个城市&#xff0c;拥有众多员工。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 客户痛点&#xff1a; 员工入离职…

怎样把照片不想要的部分涂抹掉?安利下面这三款软件给你

在元旦假期的旅行中&#xff0c;我带着相机&#xff0c;用镜头记录下了每一个美好时刻。我爬上了高山之巅&#xff0c;俯瞰群山连绵起伏&#xff1b;我漫步在海滩上&#xff0c;感受海风轻拂脸颊&#xff1b;我甚至在城市的角落里&#xff0c;发现了那些平日里未曾留意的小确幸…

Unity 踩坑记录 AnyState 切换动画执行两次

AnySate 切换动画 Can Transition To Self 将这个勾选去掉&#xff01;&#xff01;&#xff01;

树定义及遍历

1、定义树 可以参考链表&#xff0c;链表遍历不方便&#xff0c;如果单链表有多个next指针&#xff0c;则就形成了树。 Java: public class TreeNode {int val;TreeNode left, right;TreeNode(int val) { this.val val; this.left null;this.right null;} } Python&#…

【上海】买套二手房需要多少钱?

上次我们看了苏州的二手房&#xff0c;这次我们一起来看下上海的二手房价格如何。 数据来源 数据来自贝壳二手房&#xff0c;每个区最多获取了3千条房源信息&#xff0c;数据共计4万条左右 对数据感兴趣的朋友&#xff0c;公众号后台发送上海二手房获取数据文件 各区房源单价…

Linux中快速搭建RocketMQ测试环境

必要的文件下载 为什么选择RocketMQ | RocketMQ x86_64位JDK下载0jdk/8u391-b13 rocketmq二进制包下载-rocketmq-all-5.1.4-bin-release.zip 编译好的直接可用的dashboard【rocketmq-dashboard-1.0.0.jar】请在文章顶部下载 dashboard配套的配置文件【application.propert…

shell解释和权限概念

shell问题解释 问题1&#xff1a; 为什么要使用shell外壳&#xff1f; 因为用户不能直接访问操作系统 问题2&#xff1a; shell外壳是什么&#xff1f; shell外壳的工作是将使用者的命令翻译给核心&#xff08;kernel&#xff09;处理。 同时将处理结果反馈给使用者。 问…

mysql之导入导出远程备份

文章目录 一、navicat导入导出二、mysqldump命令导入导出2.1导出2.1.1 导出表数据和表结构2.1.2 只导出表结构() 2.2 导入(使用mysqldump导入 包含t _log表的整个数据库 共耗时 20s;)方法一&#xff1a;方法二&#xff1a; 三、LOAD DATA INFILE命令导入导出(只针对单表)设置导…