OpenGL紋理案例-隧道

使用OpenGL常用的API,繪制一個(gè)簡(jiǎn)單的隧道模型并貼圖。最終下過(guò)如下:


完成代碼:

#include "GLTools.h"

#include "GLShaderManager.h"

#include "GLFrustum.h"

#include "GLBatch.h"

#include "GLFrame.h"

#include "GLMatrixStack.h"

#include "GLGeometryTransform.h"

#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;? ? ? //幾何變換管線(xiàn)

//4個(gè)批次容器類(lèi)

GLBatch? ? ? ? ? ? floorBatch;//地面

GLBatch? ? ? ? ? ? ceilingBatch;//天花板

GLBatch? ? ? ? ? ? leftWallBatch;//左墻面

GLBatch? ? ? ? ? ? rightWallBatch;//右墻面

//深度初始值,-65。

GLfloat? ? ? ? ? ? viewZ = -60.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 i ;

? ? for (i = 0 ; i<TEXTURE_COUNT; i++) {


? ? ? ? glBindTexture(GL_TEXTURE_2D, textures[i]);


? ? ? ? switch(value)

? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? case 0:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 1:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 2:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 3:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 4:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 5:


? ? ? ? ? ? ? ? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? ? ? case 6:


? ? ? ? ? ? ? ? ? ? ? //設(shè)置各向異性過(guò)濾

? ? ? ? ? ? ? ? ? ? ? GLfloat fLargest;

? ? ? ? ? ? ? ? ? ? ? //獲取各向異性過(guò)濾的最大數(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è)置各向同性過(guò)濾,數(shù)量為1.0表示(各向同性采樣)

? ? ? ? ? ? ? ? ? ? ? glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);

? ? ? ? ? ? ? ? ? ? ? break;


? ? ? ? ? ? ? }

? ? }

? ? glutPostRedisplay();

}

//在這個(gè)函數(shù)里能夠在渲染環(huán)境中進(jìn)行任何需要的初始化,它這里的設(shè)置并初始化紋理對(duì)象

void SetupRC()

{

? ? glClearColor(0, 0, 0, 1);

? ? shaderManager.InitializeStockShaders();




? ? GLbyte * byte;


? ? GLint i, width, height, iComponent;

? ? GLenum eFormat;


? ? glGenTextures(TEXTURE_COUNT, textures);

? ? for (i = 0; i<TEXTURE_COUNT; i++) {


? ? ? ? glBindTexture(GL_TEXTURE_2D, textures[i]);


? ? ? ? byte = gltReadTGABits(szTextureFiles[i], &width, &height, &iComponent, &eFormat);

? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);



? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

? ? ? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


? ? ? ? glTexImage2D(GL_TEXTURE_2D, 0, iComponent, width, height, 0, eFormat, GL_UNSIGNED_BYTE, byte);

? ? ? ? glGenerateMipmap(GL_TEXTURE_2D);


? ? ? ? free(byte);

? ? }


? ? GLfloat z;

? ? floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);


? ? for (z = 60.0f; z >= 0.0f; z-= 10.0f) {


? ? ? ? floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

? ? ? ? floorBatch.Vertex3f(-10.0f, -10.0f, z);


? ? ? ? floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

? ? ? ? floorBatch.Vertex3f(10.0f, -10.0f, z);


? ? ? ? floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

? ? ? ? floorBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);


? ? ? ? floorBatch.MultiTexCoord2f(0, 0.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, 0.0f);

? ? ? ? ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);


? ? ? ? ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

? ? ? ? ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);


? ? ? ? ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);

? ? ? ? ceilingBatch.Vertex3f(-10.0f, 10.0f, z);


? ? ? ? ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.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, 1.0f, 0.0f);

? ? ? ? leftWallBatch.Vertex3f(-10.0f, -10.0f, z);


? ? ? ? leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

? ? ? ? leftWallBatch.Vertex3f(-10.0f, 10.0f, z);


? ? ? ? leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

? ? ? ? leftWallBatch.Vertex3f(-10.0f, -10.0f, z - 10.0f);


? ? ? ? leftWallBatch.MultiTexCoord2f(0, 0.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, 1.0f, 0.0f);

? ? ? ? rightWallBatch.Vertex3f(10.0f, -10.0f, z);


? ? ? ? rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);

? ? ? ? rightWallBatch.Vertex3f(10.0f, 10.0f, z);


? ? ? ? rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);

? ? ? ? rightWallBatch.Vertex3f(10.0f, -10.0f, z - 10.0f);


? ? ? ? rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);

? ? ? ? rightWallBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);


? ? }

? ? rightWallBatch.End();

}

//關(guān)閉渲染環(huán)境

void ShutdownRC(void)

{

? ? glDeleteTextures(TEXTURE_COUNT, textures);

}

//前后移動(dòng)視口來(lái)對(duì)方向鍵作出響應(yī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();

}

//改變視景體和視口,在改變窗口大小或初始化窗口調(diào)用

void ChangeSize(int w, int h)

{

? ? if (h == 0) h = 1;


? ? glViewport(0, 0, w, h);


? ? viewFrustum.SetPerspective(80, float(w)/float(h), 1, 120);

? ? projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

? ? transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

//調(diào)用,繪制場(chǎng)景

void RenderScene(void)

{

? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


? ? modelViewMatrix.PushMatrix();

? ? modelViewMatrix.Translate(0, 0, viewZ);


? ? shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);


? ? 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();

? ? glutSwapBuffers();

}

int main(int argc, char *argv[])

{

? ? gltSetWorkingDirectory(argv[0]);


? ? // 標(biāo)準(zhǔn)初始化

? ? glutInit(&argc, argv);

? ? glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

? ? glutInitWindowSize(800, 600);

? ? glutCreateWindow("Tunnel");

? ? glutReshapeFunc(ChangeSize);

? ? glutSpecialFunc(SpecialKeys);

? ? glutDisplayFunc(RenderScene);


? ? // 添加菜單入口,改變過(guò)濾器

? ? 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, "GLEW Error: %s\n", glewGetErrorString(err));

? ? ? ? return 1;

? ? }



? ? // 啟動(dòng)循環(huán),關(guān)閉紋理

? ? SetupRC();

? ? glutMainLoop();

? ? ShutdownRC();


? ? return 0;

}

紋理坐標(biāo)對(duì)應(yīng)關(guān)系如下:



總結(jié):

1.讀取的紋理可以翻轉(zhuǎn)使用,正反面都可以用來(lái)填充。

2.繪制流程:指定生成紋理ID的數(shù)量和數(shù)組 —>綁定紋理ID—>讀取.tga文件載入紋理 —>設(shè)置過(guò)濾方式和環(huán)繞 —> 設(shè)置紋理和頂點(diǎn)對(duì)應(yīng)關(guān)系 —> 綁定相應(yīng)的紋理并用對(duì)應(yīng)的批次類(lèi)繪制

3.修改紋理環(huán)繞過(guò)濾方式前,也需要綁定紋理ID

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容