OpenGL(二十三) 各向异性纹理过滤
生活随笔
收集整理的這篇文章主要介紹了
OpenGL(二十三) 各向异性纹理过滤
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
如果使用一般的紋理過濾,當觀察方向跟模型表面不是相互垂直的的情況下,會出現(xiàn)紋理信息的丟失,表現(xiàn)為圖像看上去比較模糊,如下圖所示,遠處場景的細節(jié)信息很差:
針對這種情況,可以采用同向異性過濾的方式處理紋理,在過濾紋理的時候,考慮到觀察角度不同,使紋理本身沿著模型表面傾斜的方向進行延伸。
使用如下語句查詢當前系統(tǒng)支持的最大同向異性過濾的數(shù)值,數(shù)值越大,表示沿著最大變化方向所采樣的紋理單元越多,顯示效果就越好:
GLfloat max_TexAni; //查詢允許的各向異性數(shù)量
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_TexAni);
以“ GL_TEXTURE_MAX_ANISOTROPY_EXT ”為參數(shù)調(diào)用“glTexParameterf ”函數(shù),并設置同向異性過濾的數(shù)值,就可以使設置生效。以下是經(jīng)過同向異性過濾設置的顯示效果:
遠處紋理的細節(jié)增強了很多。以下是工程代碼:
#define WindowWidth 400
#define WindowHeight 400
#define WindowTitle "OpenGL Mip紋理貼圖&&同向異性過濾"
#include <Windows.h>
#include "GL/glew.h"
#include <GL/freeglut.h>
#include <stdio.h>
#include <stdlib.h>
//定義紋理對象編號
GLuint texGround;
GLuint texWall;
GLuint texSky;
#define BMP_Header_Length 54 //圖像數(shù)據(jù)在內(nèi)存塊中的偏移量
static GLfloat angle = 0.0f; //旋轉角度
static GLfloat zPosition = 10;
// 函數(shù)power_of_two用于判斷一個整數(shù)是不是2的整數(shù)次冪
int power_of_two(int n)
{
if (n <= 0)
return 0;
return (n & (n - 1)) == 0;
}
/* 函數(shù)load_texture
28.* 讀取一個BMP文件作為紋理
29.* 如果失敗,返回0,如果成功,返回紋理編號
30.*/
GLuint load_texture(const char* file_name)
{
GLint width, height, total_bytes;
GLubyte* pixels = 0;
GLuint last_texture_ID = 0, texture_ID = 0;
// 打開文件,如果失敗,返回
FILE* pFile = fopen(file_name, "rb");
if (pFile == 0)
return 0;
// 讀取文件中圖象的寬度和高度
fseek(pFile, 0x0012, SEEK_SET);
fread(&width, 4, 1, pFile);
fread(&height, 4, 1, pFile);
fseek(pFile, BMP_Header_Length, SEEK_SET);
// 計算每行像素所占字節(jié)數(shù),并根據(jù)此數(shù)據(jù)計算總像素字節(jié)數(shù)
{
GLint line_bytes = width * 3;
while (line_bytes % 4 != 0)
++line_bytes;
total_bytes = line_bytes * height;
}
// 根據(jù)總像素字節(jié)數(shù)分配內(nèi)存
pixels = (GLubyte*)malloc(total_bytes);
if (pixels == 0)
{
fclose(pFile);
return 0;
}
// 讀取像素數(shù)據(jù)
if (fread(pixels, total_bytes, 1, pFile) <= 0)
{
free(pixels);
fclose(pFile);
return 0;
}
// 對就舊版本的兼容,如果圖象的寬度和高度不是的整數(shù)次方,則需要進行縮放
// 若圖像寬高超過了OpenGL規(guī)定的最大值,也縮放
{
GLint max;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
if (!power_of_two(width)
|| !power_of_two(height)
|| width > max
|| height > max)
{
const GLint new_width = 256;
const GLint new_height = 256; // 規(guī)定縮放后新的大小為邊長的正方形
GLint new_line_bytes, new_total_bytes;
GLubyte* new_pixels = 0;
// 計算每行需要的字節(jié)數(shù)和總字節(jié)數(shù)
new_line_bytes = new_width * 3;
while (new_line_bytes % 4 != 0)
++new_line_bytes;
new_total_bytes = new_line_bytes * new_height;
// 分配內(nèi)存
new_pixels = (GLubyte*)malloc(new_total_bytes);
if (new_pixels == 0)
{
free(pixels);
fclose(pFile);
return 0;
}
// 進行像素縮放
gluScaleImage(GL_RGB,
width, height, GL_UNSIGNED_BYTE, pixels,
new_width, new_height, GL_UNSIGNED_BYTE, new_pixels);
// 釋放原來的像素數(shù)據(jù),把pixels指向新的像素數(shù)據(jù),并重新設置width和height
free(pixels);
pixels = new_pixels;
width = new_width;
height = new_height;
}
}
// 分配一個新的紋理編號
glGenTextures(1, &texture_ID);
if (texture_ID == 0)
{
free(pixels);
fclose(pFile);
return 0;
}
// 綁定新的紋理,載入紋理并設置紋理參數(shù)
// 在綁定前,先獲得原來綁定的紋理編號,以便在最后進行恢復
GLint lastTextureID = last_texture_ID;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastTextureID);
glBindTexture(GL_TEXTURE_2D, texture_ID);
/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
130. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); */
GLfloat max_TexAni; //查詢允許的各向異性數(shù)量
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_TexAni);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_TexAni);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
140. GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels); */
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
glBindTexture(GL_TEXTURE_2D, lastTextureID); //恢復之前的紋理綁定
free(pixels);
return texture_ID;
}
void Display(void)
{
// 清除屏幕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 設置視角
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65, 1, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, zPosition, 0, 0, 0, 0, 1, 0);
glRotatef(angle, 0.0f, 1.0f, 0.0f); //旋轉
// 繪制左側墻壁以及紋理
glBindTexture(GL_TEXTURE_2D, texWall);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, -5.0f, 100.0f);
glTexCoord2f(30.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -100.0f);
glTexCoord2f(30.0f, 2.0f); glVertex3f(-5.0f, 5.0f, -100.0f);
glTexCoord2f(0.0f, 2.0f); glVertex3f(-5.0f, 5.0f, 100.0f);
glEnd();
//繪制右側墻
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(5.0f, -5.0f, 100.0f);
glTexCoord2f(30.0f, 0.0f); glVertex3f(5.0f, -5.0f, -100.0f);
glTexCoord2f(30.0f, 2.0f); glVertex3f(5.0f, 5.0f, -100.0f);
glTexCoord2f(0.0f, 2.0f); glVertex3f(5.0f, 5.0f, 100.0f);
glEnd();
//繪制地板
glBindTexture(GL_TEXTURE_2D, texGround);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, -5.0f, 100.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(5.0f, -5.0f, 100.0f);
glTexCoord2f(25.0f, 1.0f); glVertex3f(5.0f, -5.0f, -100.0f);
glTexCoord2f(25.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -100.0f);
glEnd();
//繪制頂層
glBindTexture(GL_TEXTURE_2D, texSky);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 100.0f);
glTexCoord2f(0.0f, 3.0f); glVertex3f(5.0f, 5.0f, 100.0f);
glTexCoord2f(35.0f, 3.0f); glVertex3f(5.0f, 5.0f, -100.0f);
glTexCoord2f(35.0f, 0.0f); glVertex3f(-5.0f, 5.0f, -100.0f);
glEnd();
glutSwapBuffers();
}
void SpecialKey(GLint key, GLint x, GLint y)
{
if (key == GLUT_KEY_UP)
{
zPosition += 1.0f;
}
if (key == GLUT_KEY_DOWN)
{
zPosition -= 1.0f;
}
if (key == GLUT_KEY_LEFT)
{
angle += 0.5f;
}
if (key == GLUT_KEY_RIGHT)
{
angle -= 0.5f;
}
glutPostRedisplay();
}
int main(int argc, char* argv[])
{
// GLUT初始化
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WindowTitle);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D); // 啟用紋理
texGround = load_texture("ground.bmp"); //加載紋理
texWall = load_texture("wall.bmp");
texSky = load_texture("sky.bmp");
glutDisplayFunc(&Display); //回調(diào)函數(shù)
glutSpecialFunc(&SpecialKey);
glutMainLoop(); //循環(huán)調(diào)用
return 0;
}
總結
以上是生活随笔為你收集整理的OpenGL(二十三) 各向异性纹理过滤的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 南千岛群岛离朝鲜距离多少公里?
- 下一篇: 打仗会不会牺牲 主要看运气吗?