使用不同Mip貼圖的紋理過濾模式唱凯,對(duì)一個(gè)隧道進(jìn)行渲染。代碼如下:
#include "GLTools.h"
#include "GLShaderManager.h"
#include "GLMatrixStack.h"
#include "GLFrustum.h"
#include "GLGeometryTransform.h"
//在Mac 系統(tǒng)下,`#include<glut/glut.h>` 在Windows 和 Linux上伏蚊,我們使?freeglut的靜態(tài)庫版本并且需要添加?個(gè)宏
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
GLShaderManager shaderManager; //著色器管理器
GLMatrixStack modelViewMatrix; //模型視圖矩陣
GLMatrixStack projectionMatrix; //投影矩陣
GLFrustum viewFrustum; //視景體
GLGeometryTransform transformPipeline; //幾何圖形變換管道
//4個(gè)批次容器類
GLBatch floorBatch; //地面
GLBatch ceilingBatch; //天花板
GLBatch leftWallBatch; //左墻面
GLBatch rightWallBatch; //右墻面
//深度初始值
GLfloat viewZ = -65.0f;
//紋理標(biāo)識(shí)符號(hào)
#define TEXTURE_BRICK 0 //墻面
#define TEXTURE_FLOOR 1 //地板
#define TEXTURE_CEILING 2 //紋理天花板
#define TEXTURE_COUNT 3 //紋理個(gè)數(shù)
GLuint textures[TEXTURE_COUNT]; //紋理標(biāo)記數(shù)組
//文件tag名字?jǐn)?shù)組
const char * szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };
//菜單欄選擇
void ProcessMenu(int value)
{
GLint iLoop;
for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
{
/*
綁定紋理 glBindTexture
參數(shù)1:GL_TEXTURE_2D
參數(shù)2:需要綁定的紋理對(duì)象
*/
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
/*
配置紋理參數(shù) glTexParameteri
參數(shù)1:紋理模式
參數(shù)2:紋理參數(shù)
參數(shù)3:特定紋理參數(shù)
*/
switch (value)
{
case 0:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)巡通,GL_NEAREST(最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
break;
case 1:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_LINEAR(線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
break;
case 2:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)鹃祖,GL_NEAREST_MIPMAP_NEAREST(選擇最鄰近的Mip層溪椎,并執(zhí)行最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
break;
case 3:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_NEAREST_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補(bǔ)恬口,并執(zhí)行最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
break;
case 4:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)校读,GL_NEAREST_MIPMAP_LINEAR(選擇最鄰近Mip層,并執(zhí)行線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
break;
case 5:
//GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)祖能,GL_LINEAR_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補(bǔ)歉秫,并執(zhí)行線性過濾,又稱為三線性過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
break;
case 6:
//設(shè)置各向異性過濾
GLfloat fLargest;
//獲取各向異性過濾的最大數(shù)量
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
//設(shè)置紋理參數(shù)(各向異性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
break;
case 7:
//設(shè)置各向同性過濾养铸,數(shù)量為1.0表示(各向同性采樣)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
break;
}
}
//觸發(fā)重繪
glutPostRedisplay();
}
//ChangeSize 函數(shù):?定義函數(shù).通過glutReshaperFunc(函數(shù)名)注冊(cè)為重塑函數(shù).當(dāng)屏幕??發(fā)?變化/或者第?次創(chuàng)建窗?時(shí),會(huì)調(diào)?該函數(shù)調(diào)整窗???/視???.
void ChangeSize(int w ,int h)
{
//1.防止對(duì)0進(jìn)行除法操作
if(h == 0)
h = 1;
//設(shè)置視口窗口尺寸
glViewport(0, 0, w, h);
GLfloat fAspect = (GLfloat)w/(GLfloat)h;
//創(chuàng)建投影矩陣
viewFrustum.SetPerspective(80.0f,fAspect,1.0,120.0);
//加載到投影矩陣堆棧上
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//設(shè)置變換管道以使用兩個(gè)矩陣堆棧
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
//在這個(gè)函數(shù)里能夠在渲染環(huán)境中進(jìn)行任何需要的初始化雁芙,它這里的設(shè)置并初始化紋理對(duì)象
void SetupRC()
{
//黑色的背景
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
shaderManager.InitializeStockShaders();
GLbyte * pBytes;
GLint iWidth, iHeight, iComponents;
GLenum eFormat;
GLint iLoop;
//生成紋理標(biāo)記
/*
分配紋理對(duì)象 glGenTextures
參數(shù)1:紋理對(duì)象的數(shù)量
參數(shù)2:紋理對(duì)象標(biāo)識(shí)數(shù)組
*/
glGenTextures(TEXTURE_COUNT, textures);
//循環(huán)設(shè)置紋理數(shù)組的紋理參數(shù)
for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
{
/*
綁定紋理對(duì)象 glBindTexture
參數(shù)1:紋理模式,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
參數(shù)2:需要綁定的紋理對(duì)象
*/
glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
/*
加載tga文件
參數(shù)1:紋理文件名稱
參數(shù)2:文件寬度變量地址
參數(shù)3:文件高度變量地址
參數(shù)4:文件組件變量地址
參數(shù)5:文件格式變量地址
返回值:pBytes钞螟,指向圖像數(shù)據(jù)的指針
*/
pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponents, &eFormat);
//加載紋理兔甘、設(shè)置過濾器和包裝模式
//GL_TEXTURE_MAG_FILTER(放大過濾器,GL_NEAREST(最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_NEAREST(最鄰近過濾)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//GL_TEXTURE_WRAP_S(s軸環(huán)繞),GL_CLAMP_TO_EDGE(環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//GL_TEXTURE_WRAP_T(t軸環(huán)繞),GL_CLAMP_TO_EDGE(環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/**載入紋理 glTexImage2D
參數(shù)1:紋理維度鳞滨,GL_TEXTURE_2D
參數(shù)2:mip貼圖層次
參數(shù)3:紋理單元存儲(chǔ)的顏色成分(從讀取像素圖中獲得)
參數(shù)4:加載紋理寬度
參數(shù)5:加載紋理的高度
參數(shù)6:加載紋理的深度
參數(shù)7:像素?cái)?shù)據(jù)的數(shù)據(jù)類型,GL_UNSIGNED_BYTE無符號(hào)整型
參數(shù)8:指向紋理圖像數(shù)據(jù)的指針
*/
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
/**為紋理對(duì)象生成一組完整的mipmap glGenerateMipmap
參數(shù)1:紋理維度裂明,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
*/
glGenerateMipmap(GL_TEXTURE_2D);
//釋放原始紋理數(shù)據(jù),不再需要紋理原始數(shù)據(jù)了
free(pBytes);
}
//設(shè)置幾何圖形頂點(diǎn)/紋理坐標(biāo)(上.下.左.右)
GLfloat z;
/*
GLTools庫中的容器類太援,GBatch闽晦,
void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
參數(shù)1:圖元枚舉值
參數(shù)2:頂點(diǎn)數(shù)
參數(shù)3:1組或者2組紋理坐標(biāo)
*/
floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for (z = 60.0f; z >= 0.0f; z -= 10.0f)
{
floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z);
floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
floorBatch.Vertex3f(-10.0f, -10.0f, z-10.0f);
floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
floorBatch.Vertex3f(10.0f, -10.0f, z-10.0f);
}
floorBatch.End();
ceilingBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for(z = 60.0f; z >= 0.0f; z -=10.0f)
{
ceilingBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
ceilingBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
ceilingBatch.Vertex3f(-10.0f, 10.0f, z);
ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
ceilingBatch.Vertex3f(10.0f, 10.0f, z);
}
ceilingBatch.End();
leftWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for (z = 60.0f; z >= 0.0f; z -= 10.0f)
{
leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
leftWallBatch.Vertex3f(-10.0f, -10.0f, z);
leftWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
leftWallBatch.Vertex3f(-10.0f, 10.0f, z);
leftWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
leftWallBatch.Vertex3f(-10.0f, -10.0f, z-10.0f);
leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
leftWallBatch.Vertex3f(-10.0f, 10.0f, z-10.0f);
}
leftWallBatch.End();
rightWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
for (z = 60.0f; z >= 0.0f; z -= 10.0f)
{
rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
rightWallBatch.Vertex3f(10.0f, -10.0f, z);
rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
rightWallBatch.Vertex3f(10.0f, 10.0f, z);
rightWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
rightWallBatch.Vertex3f(10.0f, -10.0f, z-10.0f);
rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
rightWallBatch.Vertex3f(10.0f, 10.0f, z-10.0f);
}
rightWallBatch.End();
}
//刪除紋理對(duì)象
void ShutdownRC(void)
{
glDeleteTextures(TEXTURE_COUNT, textures);
}
//上下左右鍵位控制移動(dòng)
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP)
{
viewZ += 0.5f;
}
if (key == GLUT_KEY_DOWN)
{
viewZ -= 0.5f;
}
glutPostRedisplay();
}
//RenderScene 函數(shù):?定義函數(shù).通過glutDisplayFunc(函數(shù)名)注冊(cè)為顯示渲染函數(shù).當(dāng)屏幕發(fā)?變化/或者開發(fā)者主動(dòng)渲染會(huì)調(diào)?此函數(shù),?來實(shí)現(xiàn)數(shù)據(jù)->渲染過程
void RenderScene(void)
{
//清理緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT);
modelViewMatrix.PushMatrix();
modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
//3.紋理替換矩陣著色器
/*
參數(shù)1:GLT_SHADER_TEXTURE_REPLACE(著色器標(biāo)簽)
參數(shù)2:模型視圖投影矩陣
參數(shù)3:紋理層
*/
shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
//4.綁定紋理
/*
參數(shù)1:紋理模式,GL_TEXTURE_1D提岔、GL_TEXTURE_2D仙蛉、GL_TEXTURE_3D
參數(shù)2:需要綁定的紋理
*/
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
floorBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
ceilingBatch.Draw();
glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
leftWallBatch.Draw();
rightWallBatch.Draw();
//模型視圖出棧
modelViewMatrix.PopMatrix();
//交換緩存區(qū)
glutSwapBuffers();
}
//main 函數(shù): 程序??.OpenGL 是?向過程編程.所以你會(huì)發(fā)現(xiàn)利?OpenGL處理圖形/圖像都是鏈?zhǔn)叫问?以及基于OpenGL封裝的圖像處理框架也是鏈?zhǔn)骄幊?int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
//申請(qǐng)一個(gè)顏色緩存區(qū)、雙緩存區(qū)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
//設(shè)置窗口的尺寸
glutInitWindowSize(800, 800);
//設(shè)置窗口的名稱
glutCreateWindow("隧道");
//注冊(cè)回調(diào)函數(shù)(改變尺寸)
glutReshapeFunc(ChangeSize);
//注冊(cè)顯示函數(shù)
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
//添加菜單
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("GL_NEAREST", 0);
glutAddMenuEntry("GL_LINEAR", 1);
glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST", 2);
glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
glutAddMenuEntry("Anisotropic Filter", 6);
glutAddMenuEntry("Anisotropic Off", 7);
glutAttachMenu(GLUT_RIGHT_BUTTON);
GLenum err = glewInit();
if (GLEW_OK != err)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
//runloop運(yùn)行循環(huán)
glutMainLoop();
ShutdownRC();
return 0;
}
運(yùn)行效果如下: