一、SOIL

SOIL是简易OpenGL图像库(Simple OpenGL Image Library)的缩写,它支持大多数流行的图像格式,关于SOIL的介绍应该很多,这里就不说了,我们先装上

OpenGL环境配置(超全整合版)SOIL库可以从这篇文章中的链接中下载到,有个叫做imple OpenGL Image Library的文件夹就是了,打开后将其src文件夹中的SOIL.h放到老位置(C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include),并用你当前的vs打开projects文件夹中的VC9解决方案,直接生成解决方案打出release包(注意选择x86或32),之后在原目录下的release文件夹中将SOIL.lib拉出来一样放入老位置(C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\lib\x86)好了搞定,我们可以再次打开VS了,这次是打开你的项目

打开项目后,菜单→项目→属性,进入如下界面,附加依赖项中添加SOIL.lib即可完成环境配置,当然你也可以将之前的glew32.lib也顺便加进去,这样就无需在代码的最开始 #pragma comment(lib,"glew32.lib")

搞定之后随意输入一份代码测试以下有没有问题,如果出现无法解析的XX方法错误,请试下使用VC8编译生成.lib文件而并非VC9

二、简单应用

如下图:我们用 OpenGL基础5:第一个正方形 这一篇文章中的代码进行扩展,让这个正方形拥有纹理

我们之前给顶点加上了位置属性和颜色属性,那么我们现在再加上第三个属性:纹理属性

GLfloat vertices[] =
{-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f
};
GLuint indices[] =
{0, 1, 2,        //用前3个顶点绘制第一个三角形1, 2, 3         //用后3个顶点绘制第二个三角形
};

前3个参数是位置,中间3个参数是颜色,后面两个参数就是纹理坐标了,上面的4个纹理坐标正好对应着4个角,(其中(0, 0)为左下角)一样注意调整 glVertexAttribPointer 方法的步长和偏移

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);

其中可以看到,我们设置了纹理坐标的位置值是2,顶点着色器当然要改

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec2 texture;
out vec4 colorIn;
out vec2 texIn;
void main()
{gl_Position = vec4(position, 1.0);colorIn = color;texIn = texture;
}

顶点着色器的修改非常容易理解,生成创建绑定的方式也和前面EBO、VBO非常相似:

GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

之后就是纹理生成部分了:

int picWidth, picHeight;
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);
unsigned char* image = SOIL_load_image("timg.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);

前面的4个 glTexParameteri 方法本章暂时不讲

  • SOIL_load_image:获取图片文件,第1个参数为图片的路径,第2个参数和第3个参数需要两个int指针,SOIL会返回图片的宽度和高度到其中,第4个参数指定图片的通道(Channel)数量,目前为0就好,最后一个参数告诉SOIL如何来加载图片:目前只需要关注图片的RGB值
  • glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image):第3个参数为纹理存储格式,目前图像只有RGB值,因此们也把纹理储存为RGB值,第4个参数和第5个参数为宽和高,我们用自己图片的宽和高就可以了,上面的方法也有给你赋值,第7个参数和第8个参数定义了源图的格式和数据类型,这里表示我们使用RGB值加载这个图像,并把它们储存为char(byte)数组,第9个参数就是我们需要的图片。其它参数暂时不需要理解

当然在这里你需要任意一张图片,注意:图片的宽高必须是2次幂(例如512 * 512,1024 * 256等),否则会出现压缩问题,后果比较严重,你也可以自己用工具修改图片的大小

片段着色器修改如下:

#version 330 core
out vec4 color;
in vec4 colorIn;
in vec2 texIn;
uniform sampler2D texOut;
void main()
{color = texture(texOut, texIn);
}
  • uniform sampler2D ourTexture:将纹理添加到片段着色器中,其中sampler为采样器,是一个供纹理对象使用的内建数据类型
  • color = texture(texOut, texIn):采样纹理的颜色,第1个参数是纹理采样器,第2个参数是对应的纹理坐标。texture函数会使用之前设置的纹理参数对相应的颜色值进行采样,这个片段着色器输出的就是当前纹理坐标上插值过滤后得到的最终颜色

最后我们只需要调用glBindTexture之前绑定的纹理就好,它会自动把纹理赋值给片段着色器的采样器

glBindTexture(GL_TEXTURE_2D, texture);
shaderYellow.Use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

完整代码:其中 Shader.h 可以在上一章找到代码,没有改动,两个着色器的代码在上面

#include<iostream>
#include<opengl/glew.h>
#define GLEW_STATIC
#include<GLFW/glfw3.h>
#include"Shader.h"
#include<opengl/freeglut.h>
#include<SOIL.h>void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
const GLuint WIDTH = 800, HEIGHT = 600;int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);glfwMakeContextCurrent(window);glfwSetKeyCallback(window, key_callback);glewExperimental = GL_TRUE;glewInit();int width, height;glfwGetFramebufferSize(window, &width, &height);glViewport(0, 0, width, height);Shader shaderYellow("VShader.txt", "FShaderY.txt");GLfloat vertices[] ={-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};GLuint indices[] ={0, 1, 2,        //用前3个顶点绘制第一个三角形1, 2, 3         //用后3个顶点绘制第二个三角形};GLuint VBO, EBO, VAO, texture;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glGenTextures(1, &texture);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBindTexture(GL_TEXTURE_2D, texture);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));glEnableVertexAttribArray(2);int picWidth, picHeight;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);unsigned char* image = SOIL_load_image("timg.jpg", &picWidth, &picHeight, 0, SOIL_LOAD_RGB);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, picWidth, picHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image);glGenerateMipmap(GL_TEXTURE_2D);SOIL_free_image_data(image);glBindTexture(GL_TEXTURE_2D, 0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);while (!glfwWindowShouldClose(window)){glfwPollEvents();glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glBindTexture(GL_TEXTURE_2D, texture);shaderYellow.Use();glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glBindVertexArray(0);glfwSwapBuffers(window);}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glfwTerminate();return 0;
}void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);
}

参考:https://learnopengl.com/

OpenGL基础8:SOIL库相关推荐

  1. OpenGL基础26:Assimp库

    一.模型文件 游戏中有很多复杂的模型往往都是美术通过3D建模工具构建出来的,当然不是程序将顶点写死在代码里的,想想看一个简单的人物模型可能就有上千个顶点,这个时候按之前"生成木箱子" ...

  2. OpenGL基础12:进入3D世界

    前置:OpenGL基础11:空间 一.坐标系 我们都学过坐标系,根据z轴的方向,一般有两种不同的坐标系表示方法: 其中拇指是x轴正方向,食指是y轴正方向,中指是z轴正方形 OpenGL约定是右手坐标系 ...

  3. OpenGL基础10:变换

    必须掌握的前置技能:https://blog.csdn.net/Jaihk662/article/details/103811465(向量与矩阵) 其实也不难,也就是一些线性代数的基本知识,暂时只需要 ...

  4. windows C++ Opengl基础框架源码

    windows C++ Opengl基础框架源码 项目开发环境 项目功能 项目演示 项目源码传送门 项目开发环境 开发语言:C++和IDE:VS2017,操作系统Windows版本windows SD ...

  5. [转]OpenGL基础技术讲座--发展历史

    OpenGL基础技术讲座--发展历史 第一讲 OpenGL 的发展历史 人们对三维图形技术的研究已经经历了一个很长的历程,而且涌现了许多三维图形开发工具,其中SGI公司推出的GL(Graphics L ...

  6. OpenGL基础54:点光源阴影

    前置: OpenGL基础53:阴影映射(下) 一.万象阴影贴图 之前成功实现了平行光阴影,生成阴影贴图时使用的矩阵是正交矩阵,若是想要实现点光源的阴影效果,那么理论上只需要修改投影矩阵为透视矩阵就好了 ...

  7. OpenGL基础50:HDR

    一.HDR与LDR 由于显示器只能显示值为0.0到1.0间的颜色,因此当数据存储在帧缓冲(Framebuffer)中时,亮度和颜色的值也是默认被限制在0.0到1.0之间的,这个颜色范围即是LDR(Lo ...

  8. OpenGL基础44:光照矫正(上)

    对于openGL的API,倒是没有必要花太多时间,重点应该还是在着色器上 一.采样器.glActiveTexture和glBindTexture 在之前测试简单光照时可能出现的两个问题,尽管它们可能不 ...

  9. OpenGL基础40:Uniform缓冲

    前置:OpenGL基础39:GLSL内建变量与接口块 想想之前代码,glUniform()和glGetUniformLocation()的使用数量是不是过于频繁了,对于每个着色器的每一个uniform ...

最新文章

  1. MongoDB给数据库创建用户
  2. hive基本操作与应用
  3. java线程状态有哪几种,顺利拿到offer
  4. java调用so库中的native方法_Java如何调用本地.so库里的方法
  5. HttpServletRequest和ServletRequest的区别
  6. java构造函数中启动线程_通过构造器启动线程的实现方式及其缺点记录。
  7. VSCode 花式玩法(摸鱼)了解一下
  8. python文件打开后闪退_python文件打开闪退要怎么处理?
  9. token与refresh_token
  10. 计算机0x50006错误,你们安装win8使用崩溃多少次
  11. DSP28335学习记录(五)——eCAP、eQEP
  12. ElasticSearch 23 种映射参数详解
  13. 安装CUDA时报错packages have unmet dependencies的一个可能原因
  14. 从Antd 源码到自我实现之 Form表单
  15. CF957D Riverside Curio
  16. 架构师的 36 项修炼第02讲:架构核心技术之分布式缓存(上)
  17. Chrome Console 小技巧之 01 如何启动XHR监控网络请求
  18. 【菜鸟】java.net.URISyntaxException: Expected scheme-specific part at index 10: localhost: 报错解决思路
  19. 将安装好的图标添加到Ubuntu桌面
  20. gitlab 挖矿病毒处理

热门文章

  1. python是什么 自学-自学python需要什么基础,要掌握哪些知识?
  2. python是什么编程语言-Python是什么?可能是最受欢迎的编程语言
  3. python与java区别-Java与Python到底有什么区别和共同点详细对比
  4. python基础教程免费视频-零基础小白python从入门到精通视频(全60集)
  5. 语音识别kaldi该如何学习?
  6. 车载语音识别问题多 车主都说不靠谱
  7. python计算空类型_python的变量 类型和存储
  8. 分类计数原理与分步计数原理_两种基础的计数原理
  9. 【python笔记】选择结构:if语句详解
  10. python实现dos攻击_python 实现DoS攻击