MipMap多层级纹理:
纹理不仅仅是一张图片数据,可能是一系列图数据,因为图片放大、缩小时纹理要进行插值计算,这个过程是比较耗时间的,为了避免这耗时的计算,提高性能,显卡采用一张图片多层级纹理方式,根据摄像机离纹理距离,采用不同层级的纹理,比如摄像机离纹理较近,选择较大的纹理,摄像机离纹理较远,选择较小的纹理。这就是多层级纹理。
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data);
代码如下:
创建多层级纹理
static unsigned createTexture(int w, int h, const void* data) {
unsigned texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// --- 放大滤波 2种
//#define GL_NEAREST 0x2600 最近点采样
//#define GL_LINEAR 0x2601 线性采样
// --- 缩小滤波 6种
//#define GL_NEAREST 0x2600 在mip基层上使用最邻近过滤
//#define GL_LINEAR 0x2601 在mip基层上使用线性过滤
//#define GL_NEAREST_MIPMAP_NEAREST 0x2700 选择最邻近的mip层,并使用最邻近过滤
//#define GL_LINEAR_MIPMAP_NEAREST 0x2701 在mip层之间使用线性插值和最邻近过滤
//#define GL_NEAREST_MIPMAP_LINEAR 0x2702 选择最邻近的mip层,使用线性过滤
//#define GL_LINEAR_MIPMAP_LINEAR 0x2703 在mip层之间使用线性插值和使用线性过滤,又称三线性mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data); //创建mipmap纹理,产生的纹理要比 glTexImage2D函数产生的纹理大一倍,因为有多个层级纹理
//gluBuild2DMipmaps 函数本质上是一个for循环 调用glTexImage2D 产生不同层级纹理
//for ()
//{
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
//}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); //设置mipMap最小层级
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4); //设置mipMap最大层级 只用到第4级
return texId;
}
绘制多层级纹理
// 绘制
static void render(GLFWwindow * window) {
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//指定数据 顶点坐标 对应 纹理坐标
Vertex cubeVertices[] =
{
{ -1.0f, -1.0f, 1.0f, 0, 0 },
{ 1.0f, -1.0f, 1.0f, 1, 0 },
{ 1.0f, 1.0f, 1.0f, 1, 1 },
{ -1.0f, 1.0f, 1.0f, 0, 1 },
{ -1.0f, -1.0f, -1.0f, 0, 0 },
{ -1.0f, 1.0f, -1.0f, 1, 0 },
{ 1.0f, 1.0f, -1.0f, 1, 1 },
{ 1.0f, -1.0f, -1.0f, 0, 1 },
{ -1.0f, 1.0f, -1.0f, 0, 0 },
{ -1.0f, 1.0f, 1.0f, 1, 0 },
{ 1.0f, 1.0f, 1.0f, 1, 1 },
{ 1.0f, 1.0f, -1.0f, 0, 1 },
{ -1.0f, -1.0f, -1.0f, 0, 0 },
{ 1.0f, -1.0f, -1.0f, 1, 0 },
{ 1.0f, -1.0f, 1.0f, 1, 1 },
{ -1.0f, -1.0f, 1.0f, 0, 1 },
{ 1.0f, -1.0f, -1.0f, 0, 0 },
{ 1.0f, 1.0f, -1.0f, 1, 0 },
{ 1.0f, 1.0f, 1.0f, 1, 1 },
{ 1.0f, -1.0f, 1.0f, 0, 1 },
{ -1.0f, -1.0f, -1.0f, 0, 0 },
{ -1.0f, -1.0f, 1.0f, 1, 0 },
{ -1.0f, 1.0f, 1.0f, 1, 1 },
{ -1.0f, 1.0f, -1.0f, 0, 1 },
};
glMatrixMode(GL_MODELVIEW);
#if 0
glEnable(GL_DEPTH_TEST);
glInterleavedArrays( GL_T2F_V3F, sizeof(Vertex), cubeVertices );
#else
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &cubeVertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &cubeVertices[0].u);
#endif
//绘制第一个立方体
// 清成单位矩阵
glLoadIdentity();
// 产生一个矩阵
glTranslatef(-2, 0, -13);
for(int i = 0; i < 6; ++i) {
glBindTexture(GL_TEXTURE_2D, _texture[i%2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);//纹理采用mipmap线性采样
glDrawArrays(GL_QUADS, i * 4, 4);
}
//绘制第二个立方体
// 清成单位矩阵
glLoadIdentity();
// 产生一个矩阵
glTranslatef(2, 0, -13);
for(int i = 0; i < 6; ++i) {
glBindTexture(GL_TEXTURE_2D, _texture[i % 2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //纹理采用mipmap最近点采样
glDrawArrays(GL_QUADS, i * 4, 4);
}
glfwSwapBuffers(window);
glfwPollEvents();
}