先上三张效果图

SampleTex.cpp

/**
* 加载纹理图片
*/
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <Shader/Shader.h>
//定义STB_IMAGE_IMPLEMENTATION,预处理器会修改头文件,让其只包含相关的函数定义源码,等于是将这个头文件变为一个 .cpp 文件了
#define STB_IMAGE_IMPLEMENTATION
#include <other/stb_image.h>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void inputProcess(GLFWwindow* window);//顶点数据
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  // 四二个三角形
};//顶点缓冲对象(Vertex Buffer Objects, VBO),它会在GPU内存(通常被称为显存)中储存大量顶点
//使用这些缓冲对象的好处是我们可以一次性的发送一大批数据到显卡上,而不是每个顶点发送一次
unsigned int VBO;
//顶点数组对象(Vertex Array Object, VAO)可以像顶点缓冲对象那样被绑定,任何随后的顶点属性调用都会储存在这个VAO中。
//这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。
unsigned int VAO;
//索引缓冲对象(Element Buffer Object,EBO,也叫Index Buffer Object,IBO)
//只储存不同的顶点,并设定绘制这些顶点的顺序,它专门储存索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点[简化一些重复的顶点定义]
unsigned int EBO;// Holds uniform value of texture mix
GLfloat mixValue = 0.2f;int main()
{
/*--------------------------------------------------------------------------------------*///初始化glfwglfwInit();//第一个参数代表选项的名称,我们可以从很多以GLFW_开头的枚举值中选择;第二个参数接受一个整型,用来设置这个选项的值//其实就是设置用Opengl哪个版本,这里是3.3版本glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//MAC系统要打开//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//创建窗口GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}//将创建的窗口上下文设置为当前线程的主上下文glfwMakeContextCurrent(window);//在调用任何OpenGL的函数之前我们需要初始化GLAD//加载系统相关的OpenGL函数指针地址if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}//设置窗口大小改变的回调glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*--------------------------------------------------------------------------------------*//**生成一个纹理*/
/*--------------------------------------------------------------------------------------*/unsigned int texture1, texture2;//生成纹理的数量和纹理IDglGenTextures(1, &texture1);//绑定图片glBindTexture(GL_TEXTURE_2D ,texture1);//在图像加载时翻转y轴stbi_set_flip_vertically_on_load(true);为当前绑定的纹理对象设置环绕、过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);int width, height, nrChannels;//宽度、高度和颜色通道的个数unsigned char* imageData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);if (imageData){/*使用前面载入的图片数据生成一个纹理1. 指定纹理目标,设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理2. 指定多级渐远纹理的级别 03. 把纹理储存为RGB格式4.5 设置图片的宽高6. 无作用7. 定义源图的格式和数据类型8. data 真正的图像数据*/glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);//为当前绑定的纹理自动生成所有需要的多级渐远纹理glGenerateMipmap(GL_TEXTURE_2D);}else {cout << "Failed to load texture" << endl;}//释放图像内存stbi_image_free(imageData);// texture 2// ---------glGenTextures(1, &texture2);glBindTexture(GL_TEXTURE_2D, texture2);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);// 加载图片,创建纹理,生成mipmapsimageData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);if (imageData){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);glGenerateMipmap(GL_TEXTURE_2D);}else{std::cout << "Failed to load texture" << std::endl;}stbi_image_free(imageData);
/*--------------------------------------------------------------------------------------*/Shader ourShader("Shader/Vertex/VertexShader.vs", "Shader/Fragment/FragmentShader.fs");ourShader.use();glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);ourShader.setInt("texture2", 1);glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);glBindVertexArray(EBO);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);//渲染循环(Render Loop),一直检测glfw窗口是否被要求关闭while (!glfwWindowShouldClose(window)){//处理按键输入inputProcess(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);// 设置一个混合变量,改变两张图的可见度glUniform1f(glGetUniformLocation(ourShader.ID, "mixValue"), mixValue);ourShader.use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);/***********这里做具体的渲染指令************///交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。glfwSwapBuffers(window);//检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。glfwPollEvents();}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);//释放或者删除之前的分配的所有资源glfwTerminate();return 0;
}//窗口大小变化的时候的回调
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{//看下宽高变化的数据printf("w = %d, h = %d \n",width, height);//设置OpenGL渲染窗口的尺寸大小(视口Viewport),前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)glViewport(0, 0, width, height);
}//处理按键输入
void inputProcess(GLFWwindow* window)
{//按下ESC的时候if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){//把WindowShouldClose属性设置为 true,在循环肿关闭窗口glfwSetWindowShouldClose(window, true);printf("窗口即将关闭...");}// 改变可见度的变量if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS){mixValue += 0.1f;if (mixValue >= 1.0f)mixValue = 1.0f;}if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS){mixValue -= 0.1f;if (mixValue <= 0.0f)mixValue = 0.0f;}
}

VertexShader.vs

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;out vec3 ourColor;
out vec2 TexCoord;void main()
{gl_Position = vec4(aPos, 1.0);ourColor = aColor;TexCoord = aTexCoord;
}

FragmentShader.fs

#version 330 core
out vec4 FragColor;//顶点着色器过来的纹理颜色
in vec3 ourColor;
//顶点着色器过来的纹理坐标
in vec2 TexCoord;//2D纹理的采样器
uniform sampler2D texture1;
uniform sampler2D texture2;//设定一个变量,通过按键控制纹理可见度
uniform float mixValue;void main()
{//使用GLSL内建的texture函数来采样纹理的颜色,它第一个参数是纹理采样器,第二个参数是对应的纹理坐标。//把纹理颜色与顶点颜色在片段着色器中相乘来混合二者的颜色//FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0);//接受两个值作为参数,并对它们根据第三个参数进行线性插值。如果第三个值是0.0,它会返回第一个输入;//如果是1.0,会返回第二个输入值。//0.2会返回80%的第一个输入颜色和20%的第二个输入颜色,即返回两个纹理的混合色FragColor = mix(texture(texture1, TexCoord), texture(texture2, vec2(1.0 - TexCoord.x, TexCoord.y)), mixValue);
}

stb_image.h的话直接在github下载

https://github.com/nothings/stb/blob/master/stb_image.hhttps://github.com/nothings/stb/blob/master/stb_image.h

原文:纹理 - LearnOpenGL CN

特别需要注意的就是宏文件一定要定义:

#define STB_IMAGE_IMPLEMENTATION
#include <other/stb_image.h>

然后图片的话直接放在根目录吧,不然加载始终有点问题

unsigned char* imageData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);

这里的container.jpg放在项目根目录读取才没问题,暂时没想再去纠结路径的问题了

Opengl加载与创建纹理相关推荐

  1. 关于openGL加载贴图纹理映射中Unknown DIB file format问题

    关于openGL加载贴图纹理映射中Unknown DIB file format问题 今天做作业发现代码可以正常编译运行,但是生成图像时显示Unknown DIB file format,后来发现是图 ...

  2. 使用 wxImage 为 OpenGL 加载纹理

    使用 wxImage 为 OpenGL 加载纹理 使用 wxImage 为 OpenGL 加载纹理 使用 wxImage 为 OpenGL 加载纹理 您可以使用 wxImage 为 OpenGL 加载 ...

  3. OpenGL加载纹理glGenTextures——内存优化(OpenGL内存泄漏)

    前言 先上图看我程序在加载纹理时,内存泄漏情况: 正常内存大小 5分钟内存泄漏情况 因为程序一直在接收二维数组(图像像素数据)然后实时绘制到界面,所以会一直加载纹理图像,OpenGL产生纹理id函数g ...

  4. OpenGL加载2D的草地

    引自: https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/ 1,如果一张2D的草地是这样的,但是背景会有一部分 ...

  5. three.js加载和使用纹理-加载DDS、PVR、TGA格式的纹理(vue中使用three.js73)

    加载DDS.PVR.TGA格式的纹理 1.demo效果 2. 实现要点 2.1 加载DDS格式纹理 2.2 加载PVR格式纹理 2.3 加载TGA格式纹理 3. demo代码 1.demo效果 以上三 ...

  6. opengl加载显示3D模型UC类型文件

    opengl加载显示3D模型UC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示uc格式的三维模型文件, 注意事项 源代码 model_ ...

  7. opengl加载显示3D模型3d类型文件

    opengl加载显示3d模型UC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示3d格式的三维模型文件, 注意事项 源代码 model_ ...

  8. opengl加载显示3DS模型3DS类型文件

    opengl加载显示3DS模型UC类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示3DS格式的三维模型文件 注意事项 源代码 model ...

  9. opengl加载显示3D模型3MF类型文件

    opengl加载显示3D模型3MF类型文件 前置条件 注意事项 项目展示 项目完整C++源代码 前置条件 opengl三方库freeglut,显示3MF格式的三维模型文件 注意事项 源代码 model ...

最新文章

  1. 大规模数据处理Apache Spark开发
  2. Linux TOP 命令显示详情
  3. Oracle等待事件说明
  4. python md5解密_python写一个md5解密器示例
  5. 一步一步写算法(之爬楼梯)
  6. *第七周*数据结构实践项目二【建设链式队列算法库】
  7. MySQL数据库迁移注意点
  8. c语言编程运行符号是什么,c语言编程用的符号有哪些
  9. Vue-Devtools 安装教程
  10. java中POJO、PO、BO、VO、DTO和DAO的概念
  11. 重装linux式化磁盘,最详细的linux系统重装步骤图解
  12. VOT 2019 RGB-TIR数据集下载教程
  13. 新浪微博开发平台试用
  14. 绘王两款便携数位屏同时发售,全贴合防眩光屏配硬笔
  15. redit mysql_如何搭建自己的网站?
  16. 6、信息隐藏技术:空域下的信息隐藏
  17. 新版androd studio怎样连接第三方模拟器
  18. OpenLayers:加载GeoServer发布的WMTS、TMS服务
  19. 用户名+密码控制+php文件存储
  20. uedit php,laravel uedit上传oss

热门文章

  1. 关于vue-cli3的浏览器兼容性
  2. AI 黑科技,老照片修复,模糊变高清
  3. QQ音乐酷狗音乐竞品分析
  4. 安卓APP开发发展趋势与前景
  5. 【AI达人创造营三期】在地平线X3上部署车牌识别系统
  6. Java正则表达式(超详细)
  7. python画笔粗细函数_Python 画图基础操作详解
  8. 国家地址json记录
  9. python装饰器原理wraps(method)(self)_理解Python中装饰器最佳方法~
  10. C# .Net 邮箱发送含附件方法