多纹理贴图:
即在一个三角形面上贴多张纹理。opengl 中很多地方都需要多纹理,法线贴图至少需要三张纹理,凹凸贴图。
//激活纹理单元0 下面操作针对这个纹理单元0
glActiveTextureARB(GL_TEXTURE0_ARB);
...
//启用纹理数组 第0个纹理单元
glClientActiveTextureARB(GL_TEXTURE0_ARB);
代码如下:
//顶点数据
struct Vertex {
float x, y, z;
float u, v;
};
//纹理ID
GLuint _texture1;
GLuint _texture2;
float _textureV = 0;;
static unsigned createTexture(int w, int h, const void* data) {
unsigned texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
return texId;
}
/**
* 使用FreeImage加载图片
*/
static unsigned createTextureFromImage(const char* fileName) {
//1 获取图片格式
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
if(fifmt == FIF_UNKNOWN) {
return 0;
}
//2 加载图片
FIBITMAP *dib = FreeImage_Load(fifmt, fileName, 0);
FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);
//! 获取数据指针
FIBITMAP* temp = dib;
dib = FreeImage_ConvertTo32Bits(dib);
FreeImage_Unload(temp);
BYTE* pixels = (BYTE*)FreeImage_GetBits(dib);
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
for(int i = 0; i < width * height * 4; i+=4) {
BYTE temp = pixels[i];
pixels[i] = pixels[i + 2];
pixels[i + 2] = temp;
}
unsigned res = createTexture(width, height, pixels);
FreeImage_Unload(dib);
return res;
}
static void onInit() {
_texture1 = createTextureFromImage("../res/1.jpg");
_texture2 = createTextureFromImage("../res/2.png");
}
static void onDestory() {
// glDeleteTextures (GLsizei n, const GLuint *textures);
// n 表示销毁几个纹理
// 纹理id数据所在数组位置
glDeleteTextures(1, &_texture1);
glDeleteTextures(1, &_texture2);
}
// 绘制
static void render(GLFWwindow * window) {
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#if 1
//传统传递数据方式 低效
glMatrixMode(GL_MODELVIEW);
// 清成单位矩阵
glLoadIdentity();
// 产生一个矩阵
glTranslatef(0, 0, -4);
//之前演示实例都是操作一个纹理单元,openlg默认就一个0,所以没有必要进行下面的操作
//激活纹理单元0 下面操作针对这个纹理单元0
glActiveTextureARB(GL_TEXTURE0_ARB);
//对这个纹理单元启动纹理
glEnable(GL_TEXTURE_2D);
//设置纹理_texture1 放到第0个纹理单元上
glBindTexture(GL_TEXTURE_2D, _texture1);
//激活纹理单元1 下面操作针对这个纹理单元1
glActiveTextureARB(GL_TEXTURE1_ARB);
//对这个纹理单元启动纹理
glEnable(GL_TEXTURE_2D);
//设置纹理_texture2 放到第0个纹理单元上
glBindTexture(GL_TEXTURE_2D, _texture2);
glBegin(GL_QUADS);
// 给多纹理单元传递数据 设置纹理坐标 顶点坐标
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 1.0f); //对纹理单元0 设置纹理坐标(0.0f, 1.0f)
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 1.0f); //对纹理单元1 设置纹理坐标(0.0f, 1.0f)
glVertex3f(-1, 1, 0); //设置顶点坐标
// 给多纹理单元传递数据 设置纹理坐标 顶点坐标
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 0.0f);
glVertex3f(-1, -1, 0);
// 给多纹理单元传递数据 设置纹理坐标 顶点坐标
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 0.0f);
glVertex3f(1, -1, 0);
// 给多纹理单元传递数据 设置纹理坐标 顶点坐标
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 1.0f);
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 1.0f);
glVertex3f(1, 1, 0);
glEnd();
#else
// 使用顶点数组的方式 传递数据 高效方法
Vertex cubeVertices[] =
{
{ -1.0f, -1, 1.0f, 0, 0 },
{ 1.0f, -1, 1.0f, 1, 0 },
{ 1.0f, 1, 1.0f, 1, 1 },
{ -1.0f, 1, 1.0f, 0, 1 },
};
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _texture1);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _texture2);
glMatrixMode(GL_MODELVIEW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &cubeVertices[0].x);
//启用纹理数组 第0个纹理单元
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &cubeVertices[0].u);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//启用纹理数组 第1个纹理单元
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &cubeVertices[0].u);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// 清成单位矩阵
glLoadIdentity();
// 产生一个矩阵
glTranslatef(0, 0, -4);
glDrawArrays(GL_QUADS, 0, 4);
#endif
glfwSwapBuffers(window);
glfwPollEvents();
}