为什么要用mipmap?
在三维世界中,显示一张图片的大小与摄像机的位置有关,近的地方,图片实际像素大一些,远 的地方,图片实际像素就小一些,比如一张64*64的图片
在近处, 显示出来可能是50*50,远处可能显示出来就是20*20。
mipmap纹理技术是目前解决纹理分辨率与视点距离关系的最有效途径,它会先将图片压缩成很多逐渐缩小的图片,例如一张64*64的图片,会产生64*64,32*32,16*16,8*8,4*4,2*2,1*1的7张图片,当屏幕上需要绘制像素点为20*20时,程序只是利用32*32和16*16 这两张图片来计算出即将显示为20*20大小的一个图片,这比单独利用32*32的哪张原始图片计算出来的图片效果好很多,速度也快。
效果图:(GL_LINEAR_MIPMAP_LINEAR过滤模式)
Mipmap过滤
Mipmap的纹理过滤模式如下表:
常量 | 描述 |
GL_NEAREST | 在mip基层上使用最邻近过滤 |
GL_LINEAR | 在mip基层上使用线性过滤 |
GL_NEAREST_MIPMAP_NEAREST | 选择最邻近的mip层,并使用最邻近过滤 |
GL_NEAREST_MIPMAP_LINEAR | 在mip层之间使用线性插值和最邻近过滤 |
GL_LINEAR_MIPMAP_NEAREST | 选择最邻近的mip层,使用线性过滤 |
GL_LINEAR_MIPMAP_LINEAR | 在mip层之间使用线性插值和使用线性过滤,又称三线性mipmap |
GL_NEAREST_MIPMAP_NEAREST 过滤模式:
shader实现类:
#pragma once
#include <assert.h>
class ShaderId
{
public:
ShaderId()
{
_shaderId = -1;
}
int _shaderId;
};
/**
* 程序
*/
class ProgramId
{
public:
int _programId;
ShaderId _vertex;
ShaderId _fragment;
public:
ProgramId()
{
_programId = -1;
}
public:
/**
* 加载函数
*/
bool createProgram(const char* vertex, const char* fragment)
{
bool error = false;
do
{
if (vertex)
{
_vertex._shaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertex._shaderId, 1, &vertex, 0);
glCompileShader(_vertex._shaderId);
GLint compileStatus;
glGetShaderiv(_vertex._shaderId, GL_COMPILE_STATUS, &compileStatus);
error = compileStatus == GL_FALSE;
if (error)
{
GLchar messages[256];
glGetShaderInfoLog(_vertex._shaderId, sizeof(messages), 0, messages);
assert(messages && 0 != 0);
break;
}
}
if (fragment)
{
_fragment._shaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragment._shaderId, 1, &fragment, 0);
glCompileShader(_fragment._shaderId);
GLint compileStatus;
glGetShaderiv(_fragment._shaderId, GL_COMPILE_STATUS, &compileStatus);
error = compileStatus == GL_FALSE;
if (error)
{
GLchar messages[256];
glGetShaderInfoLog(_fragment._shaderId, sizeof(messages), 0, messages);
assert(messages && 0 != 0);
break;
}
}
_programId = glCreateProgram();
if (_vertex._shaderId)
{
glAttachShader(_programId, _vertex._shaderId);
}
if (_fragment._shaderId)
{
glAttachShader(_programId, _fragment._shaderId);
}
glLinkProgram(_programId);
GLint linkStatus;
glGetProgramiv(_programId, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE)
{
GLchar messages[256];
glGetProgramInfoLog(_programId, sizeof(messages), 0, messages);
break;
}
glUseProgram(_programId);
} while (false);
if (error)
{
if (_fragment._shaderId)
{
glDeleteShader(_fragment._shaderId);
_fragment._shaderId = 0;
}
if (_vertex._shaderId)
{
glDeleteShader(_vertex._shaderId);
_vertex._shaderId &#