【学习笔记】OpenGL的基础纹理贴图相关知识
加载纹理图像文件
- 用于保存纹理图像的纹理对象(在本章中我们仅考虑 2D 图像);
- 特殊的统一采样器变量,以便顶点着色器访问纹理;
- 用于保存纹理坐标的缓冲区;
- 用于将纹理坐标传递给管线的顶点属性;
- 显卡上的纹理单元。
使用SOIL2读取纹理
封装读取代码
GLuint loadTexture(const char *texImagePath) {
GLuint textureID;
textureID = SOIL_load_OGL_texture(texImagePath,
SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
if (textureID == 0) cout << "could not find texture file" << texImagePath << endl;
return textureID;
}
纹理坐标
纹理坐标是对纹理图像(通常是 2D 图像)中的像素的引用。
2D 纹理坐标最为常见(OpenGL 确实支持其他一些维度,但本章不会介绍它们)。2D 纹理图像被设定为矩形,左下角的位置坐标为(0,0),右上角的位置坐标为(1,1)。理想情况下,纹理坐标应该在[0, 1]区间内取值。
构建纹理对象
GLuint brickTexture = Utils::loadTexture("brick1.jpg");
构建纹理坐标
思考如何将纹理的坐标和几何体的顶点相对应,并构造
将纹理坐标载入缓冲区
以用与前面加载顶点相似的方式将纹理坐标加载到 VBO 中。所以会有一个顶点VBO,一个纹理坐标VBO。
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyrTexCoords), pyrTexCoords, GL_STATIC_DRAW)
在着色器中使用纹理:采样器变量和纹理单元
声明一个采样器变量
layout (binding=0) uniform sampler2D samp;
激活纹理单元并将其绑定到特定的纹理对象
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, brickTexture);
修改片段着色器输出颜色的方式
in vec2 tc; // 纹理坐标
...
color = texture(samp, tc);
纹理贴图:示例程序
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <SOIL2\soil2.h>
#include <string>
#include <iostream>
#include <fstream>
#include <cmath>
#include <glm\glm.hpp>
#include <glm\gtc\type_ptr.hpp> // glm::value_ptr
#include <glm\gtc\matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective
#include "Utils.h"
using namespace std;
#define numVAOs 1
#define numVBOs 2
float cameraX, cameraY, cameraZ;
float pyrLocX, pyrLocY, pyrLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
// variable allocation for display
GLuint mvLoc, projLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvMat;
GLuint brickTexture;
void setupVertices(void) {
float pyramidPositions[54] =
{
-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, //front
1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, //right
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, //back
-1.0f, -