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

图片纹理贴图

/*
* 当需要给图形赋予真实颜色的时候,不太可能为没一个顶点指定一个颜色,通常会采用纹理贴图
* 每个顶点关联一个纹理坐标 (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// 构造函数读取并构建 shaderMyShader(const char* vertexPath, const char* fragmentPath);// 使用激活 Shadervoid 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;/*******************************************函数***************************************************///初始化GLFWglfwInit();// 初始化GLFWif (!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的函数前需要初始化gladif (!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);// 绑定 EBOglBindBuffer(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);//绑定VAOglBindVertexArray(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;}

在这里插入图片描述

相关文章:

  • VPC网络架构下的网络上数据采集
  • MIT 6.s081前置xv6教材和课程总结——第二章 操作系统架构
  • golang学习-匿名函数和闭包
  • c#调试程序一次启动两个工程(多个工程)
  • 服务器GPU温度过高挂掉排查记录
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • 避免重复扣款:分布式支付系统的幂等性原理与实践
  • astadmin安装querylist插件Puppeteer
  • 图像分类任务的可视化脚本,生成类别json字典文件
  • Hotspot源码解析-第十七章-虚拟机万物创建(三)
  • 如何使用PHP开发缓存优化图片加载速度
  • Python pip 常用指令
  • 安达发|APS智能排产软件有哪些条件约束功能
  • 2024年AIGC趋势展望:视频生成的“百模大战”
  • 每日一篇英语文章分享-----主目录-----持续更新
  • [Vue CLI 3] 配置解析之 css.extract
  • bootstrap创建登录注册页面
  • create-react-app项目添加less配置
  • Druid 在有赞的实践
  • Hexo+码云+git快速搭建免费的静态Blog
  • node学习系列之简单文件上传
  • PHP的类修饰符与访问修饰符
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • vue-router的history模式发布配置
  • 大整数乘法-表格法
  • 诡异!React stopPropagation失灵
  • 如何实现 font-size 的响应式
  • 因为阿里,他们成了“杭漂”
  • 云大使推广中的常见热门问题
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • $.ajax()
  • (2)STM32单片机上位机
  • (2022 CVPR) Unbiased Teacher v2
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (新)网络工程师考点串讲与真题详解
  • (转)EXC_BREAKPOINT僵尸错误
  • .Family_物联网
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .net mvc 获取url中controller和action
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET连接MongoDB数据库实例教程
  • .NET中winform传递参数至Url并获得返回值或文件
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [AHOI2009]中国象棋 DP,递推,组合数
  • [ajaxupload] - 上传文件同时附件参数值
  • [Bada开发]初步入口函数介绍
  • [C++]STL之map
  • [hdu 2826] The troubles of lmy [简单计算几何 - 相似]
  • [HDU] 1054 Strategic Game 入门树形DP
  • [IMX6DL] CPU频率调节模式以及降频方法
  • [LeetCode]--61. Rotate List
  • [one_demo_12]递归打印*\n*.*.\n*..*..\n图形
  • [Paper]Cardiologist-Level Arrhythmia Detection with Convolutional Neural Networks