10、OpenGL初探之OpenGL紋理及金字塔紋理繪制實(shí)戰(zhàn)

? ? 德者,本也。財(cái)者,末也。但行好事,莫問前程。

一、認(rèn)識(shí)紋理


? ? ? ? ? 紋理是什么?你可以把它理解成一張貼紙一樣的東西,在物體表面貼上圖案,紋理的作用就是用來裝飾我們的物體模型,就像裝修的時(shí)候,在家里的墻壁上貼墻紙一樣,當(dāng)然紋理的作用應(yīng)該遠(yuǎn)遠(yuǎn)不止這些。

個(gè)人思考:在一些游戲場景中,特別是地圖,比如吃雞這種主機(jī)游戲,場景都是用很多相同的,類似3D紋理的立體圖形拼出來的,比如一片草地,一片樹林,一片房屋,這些3D場景和墻紙及紋理的定義沒有本質(zhì)上的區(qū)別,不知廣義上把這些“場景貼紙”稱為紋理合不合適?大佬可以在評(píng)論區(qū)告知我或者可以一起討論。

二、紋理基礎(chǔ)


? ? 了解紋理基礎(chǔ)之前,讓我們先來了解一下圖像的存儲(chǔ)

1、原始圖像數(shù)據(jù)在內(nèi)存中的存儲(chǔ)

圖像占用的存儲(chǔ)空間 = 圖像的高度 * 圖像的寬度 * 每個(gè)像素點(diǎn)的字節(jié)數(shù)

2、認(rèn)識(shí)OpenGL圖像存儲(chǔ)相關(guān)函數(shù)

1、改變像素存儲(chǔ)方式

void glPixelStorei(GLenum pname, GLint param)

2、恢復(fù)像素存儲(chǔ)方式

void glPxielStoref (GLenum pname, GLFloat param)

參數(shù)1:GL_UNPACK_ALIGNMENT,指定OpenGL如何從數(shù)據(jù)緩存區(qū)中解包圖像數(shù)據(jù);

參數(shù)2:表示參數(shù)GL_UNPACK_ALIGNMENT設(shè)置的值。GL_UNPACK_ALIGNMENT指內(nèi)存中的每一個(gè)像素行起點(diǎn)的排列請(qǐng)求,允許設(shè)置為1(byte排列)、2(排列為偶數(shù)byte的行)、4(字word排列)8(行從雙字節(jié)邊界開始)

例:glPxielStorei(GL_UNPACK_ALIGNMENT, 1)

3、從顏色緩沖區(qū)內(nèi)容作為像素圖直接讀取(重要)

void glReadPixels(GLint x,? GLint y, GLSizei width, GLSizei height, GLenum format, GLenum type, const void*pixels);

參數(shù)1:x,矩形左下角的窗口坐標(biāo)x值

參數(shù)2:y,矩形左下角的窗口坐標(biāo)y值

參數(shù)3:width,矩形的寬,以像素為單位

參數(shù)4:height,矩形的高,以像素為單位

參數(shù)5:format,OpenGL的像素格式,參照下表1

參數(shù)6:type,解釋參數(shù)pxiels指向的數(shù)據(jù),告訴OpenGL使用緩沖區(qū)的什么數(shù)據(jù)類型來存儲(chǔ)顏色分量,像素?cái)?shù)據(jù)的數(shù)據(jù)類型,參照下表2

參數(shù)7:pxiels,指向圖形數(shù)據(jù)的指針


表1、OpenGL的像素格式,常用的是GL_RGB和GL_RGBA
表2、像素?cái)?shù)據(jù)的數(shù)據(jù)類型,常用的有GL_UNSIGNED_INT

4、載入紋理

void glTexImage1D(GLenum target , GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, void*data)

void glTexImage2D(GLenum target , GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void*data)

void glTexImage3D(GLenum target , GLint level, GLint internalformat, GLsizei width, GLsizei height,GLsizei depth, GLint border, GLenum format, GLenum type, void*data)

參數(shù)1:target:GL_TEXTURE_2D,GL_TEXTURE_1D, GL_TEXTURE_3D

參數(shù)2:level指定所加載的mip貼圖層次,一般我們都把這個(gè)參數(shù)設(shè)置為0.

參數(shù)3:internalformat:每個(gè)紋理單元中存儲(chǔ)多少顏色成分。

參數(shù)4:width,height,depth參數(shù):指的是加載紋理的寬度、高度、深度;需要注意的是這些數(shù)必須是2的整數(shù)次方。這個(gè)因?yàn)镺penGL舊版本上遺留下的一個(gè)要求,當(dāng)然現(xiàn)在已經(jīng)支持可以不是2的整數(shù)次方,但是開發(fā)者已經(jīng)習(xí)慣使用2的證書此房去設(shè)置這些參數(shù)。

參數(shù)5:border:允許為紋理貼圖制定一個(gè)邊界寬度

參數(shù)6:format、type、data參數(shù)與glDrawPxiels函數(shù)對(duì)于的參數(shù)相同。

5、更新紋理

void glTexSubImage1D(GLenum target,GLint level,GLint xOffset, GLint yoffset,GLSizei width, GLenum format, GLenum type,const? GLvoid * data)

void glTexSubImage2D(GLenum target,GLint level,GLint xOffset, GLint yoffset,GLSizei width, GLSizei height, GLenum format, GLenum type,const? GLvoid * data)

void glTexSubImage3D(GLenum target,GLint level,GLint xOffset, GLint yoffset,GLSizei width, GLSizei height,GLsizei depth, GLenum format, GLenum type,const? GLvoid * data)

1D,2D,3D的區(qū)別只在于3D比1D多了depth.height,2D只比1D多了height

6、插入替換紋理

void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset,GLsizei width,GLsizei height)

void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yOffset,GLsizei width,GLsizei height)

void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yOffset,GLint zOffset,GLsizei width,GLsizei height)

1D,2D,3D的區(qū)別只在于1D只有xOffset,2D有xOffset yOffset,3D比2D多了zOffset

7、使用顏色緩沖區(qū)加載數(shù)據(jù),形成新的紋理使用

void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,GLsizei width, GLint border)

void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y,GLsizei width, GLsizei height, GLint border)

x,y在顏色緩沖區(qū)中指定了開始讀取紋理數(shù)據(jù)的位置:緩沖區(qū)里面的數(shù)據(jù)是源緩沖區(qū)通過glReadBuffer設(shè)置的

注意:不存在glCopyTexImage3D,因?yàn)槲覀儫o法從2D顏色緩沖區(qū)中獲取體積數(shù)據(jù)

8、使用函數(shù)分配紋理對(duì)象(重要)

指定紋理對(duì)象的數(shù)量和指針,(指針指向一個(gè)無符號(hào)整形數(shù)據(jù),由紋理對(duì)象標(biāo)識(shí)符填充)

void glGenTexTures(GLsizei n,GLuint * textures);

9、綁定紋理狀態(tài)(重要)

void glBindTexture(GLenum target, GLunit texture);

參數(shù)1:target:GL_TEXTURE_2D,GL_TEXTURE_1D, GL_TEXTURE_3D

參數(shù)2:需要綁定的紋理對(duì)象

10、刪除綁定紋理對(duì)象(重要)

void glDeleteTexture(GLsizei n, GLuint * texture);

紋理對(duì)象以及紋理對(duì)象指針(指針指向一個(gè)無符號(hào)整形數(shù)組,由紋理對(duì)象標(biāo)識(shí)符填充)

11、測試紋理對(duì)象是否有效

如果texture是一個(gè)已經(jīng)分配空間的紋理對(duì)象,那么這個(gè)函數(shù)會(huì)返回GL_TURE,否則會(huì)返回GL_FALST

GLboolean glIsTexture(GLuint texture);

12、設(shè)置紋理參數(shù)

glTextureParameter(GLenum target, GLenum pname, GLFloat param);

glTextureParameter(GLenum target, GLenum pname, GLint param);

glTextureParameter(GLenum target, GLenum pname, GLFloat * param);

glTextureParameter(GLenum target, GLenum pname, GLint *param)

參數(shù)1:target,指定這些參數(shù)應(yīng)用哪個(gè)紋理模式上,比如GL_TEXTURE_2D,GL_TEXTURE_1D, GL_TEXTURE_3D

參數(shù)2:pname,指定需要設(shè)置哪個(gè)紋理參數(shù)

參數(shù)3:設(shè)定特定的紋理參數(shù)的值

13、設(shè)置過濾方式(也叫取樣)(重點(diǎn))

1、鄰近過濾 GL_NEAREST

鄰近過濾是最簡單最快速的過濾方法,它總是把最鄰近的紋理單元取到紋理坐標(biāo)中。

圖3、鄰近過濾

2、線性過濾GL_LINEAR

線性過濾會(huì)把這個(gè)紋理坐標(biāo)周圍的紋理單元加權(quán)平均值應(yīng)用到這個(gè)紋理坐標(biāo)中。周圍坐標(biāo)的紋理單元距離越近,則權(quán)值越大

圖4、線性過濾

一般建議紋理縮小用鄰近過濾,紋理放大用線性過濾,當(dāng)然你也可以隨意搭配

glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

14、設(shè)置環(huán)繞方式

glTextParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAR_S, GL_CLAMP_TO_EDGE);

glTextParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAR_T, GL_CLAMP_TO_EDGE)

參數(shù)1: GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D

參數(shù)2:GL_TEXTURE_WRAP_S、GL_TEXTURE_T、GL_TEXTURE_R,針對(duì)s,t,r坐標(biāo)

S 、T、 R 坐標(biāo)系對(duì)應(yīng)著世界坐標(biāo)系的X, Y, Z

參數(shù)3:GL_REPEAT、GL_CLAMP、GL_CLAMP_TO_EDGE、GL_CLAMP_TO_BORDER

GL_REPEAT:OpenGL 在紋理坐標(biāo)超過1.0的?向上對(duì)紋理進(jìn)?重復(fù);

GL_CLAMP:所需的紋理單元取?紋理邊界或TEXTURE_BORDER_COLOR.

GL_CLAMP_TO_EDGE環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或者最后?列來進(jìn)行采樣。

GL_CLAMP_TO_BORDER:在紋理坐標(biāo)在0.0到1.0范圍之外的只使?邊界紋理單元。邊界紋理單元是作為圍繞基本圖像的額外的?和列列,并與基本紋理圖像?起加載的

圖5、環(huán)繞方式
圖6、環(huán)繞方式圖示

三、金字塔繪制及紋理填充



圖7,金字塔模型是由6個(gè)三角形組成的(側(cè)面4個(gè)三角形,底部兩個(gè)三角形拼接)


圖8金字塔實(shí)現(xiàn)并填充紋理思維導(dǎo)圖(圖像轉(zhuǎn)載自簡書用戶CC老師_HelloCoder)

1、主函數(shù)中設(shè)置環(huán)境及注冊(cè)函數(shù)

intmain(intargc,char* argv[])

{

? ? gltSetWorkingDirectory(argv[0]);

?? ?glutInit(&argc, argv);

? ? glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);

? ? glutInitWindowSize(800, 600);

? ? glutCreateWindow("Pyramid");

? ? glutReshapeFunc(ChangeSize);

? ? glutSpecialFunc(SpecialKeys);

? ? glutDisplayFunc(RenderScene);

? ? GLenum err = glewInit();


? ? if(GLEW_OK!= err) {

? ? ? ? fprintf(stderr,"GLEW Error: %s\n",glewGetErrorString(err));

? ? ? ? return1;

? ? }

? ? SetupRC();

? ? glutMainLoop();

? ? ShutdownRC();//重要,紋理綁定后需要進(jìn)行解綁

? ? return 0;

}

2、定義全局變量

GLShaderManager shaderManager;//著色器程序

GLMatrixStack modelViewMatrix;//模型視圖矩陣

GLMatrixStack projectionMatrix;

GLFrame cameraFrame;//觀察者坐標(biāo)

GLFrame? ? ? ? ? ? objectFrame;//對(duì)象坐標(biāo)

GLFrustum viewFrustum;//

GLBatch? ? ? ? ? ? pyramidBatch;//金字塔

GLuint? ? ? ? ? ? ? textureID;//紋理變量,一般使用無符號(hào)整型

GLGeometryTransform transformPipeline;

M3DMatrix44f shadowMatrix;

3、開始設(shè)置環(huán)境

voidSetupRC()

{

? ? //1.初始化著色器,設(shè)置清屏顏色

? ? glClearColor(0.7f, 0.7f, 0.7f, 1.0f );

? ? shaderManager.InitializeStockShaders();

? ? //2.開啟深度測試

? ? glEnable(GL_DEPTH_TEST);

? ? //3.分配紋理對(duì)象

? ? // 參數(shù)1:紋理對(duì)象個(gè)數(shù),金字塔的5個(gè)面,共6個(gè)三角形,但是用的是同一個(gè)紋理,所以紋理對(duì)象個(gè)數(shù)為1。

//參數(shù)2:紋理對(duì)象指針,之前定義過了紋理對(duì)象,直接拿下來取地址就行了

? ? glGenTextures(1, &textureID);

? ? //4、綁定紋理狀態(tài)?

? ?//參數(shù)1:紋理狀態(tài)2D 參數(shù)2:紋理對(duì)象

? ? glBindTexture(GL_TEXTURE_2D, textureID);

? ? //將TGA文件加載為2D紋理。

? ? //參數(shù)1:紋理文件名稱

? ? //參數(shù)2&參數(shù)3:需要縮小&放大的過濾器

? ? //參數(shù)4:紋理坐標(biāo)環(huán)繞模式

? ? LoadTGATexture("stone.tga", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, GL_CLAMP_TO_EDGE);

? ? //5.創(chuàng)造金字塔pyramidBatch

? ? MakePyramid(pyramidBatch);

? ? //6.調(diào)整觀察者位置

? ? /**相機(jī)frame MoveForward(平移)

? ? 參數(shù)1:Z,深度(屏幕到圖形的Z軸距離)

?? ? */

? ? cameraFrame.MoveForward(-10);

}

4、渲染場景

步驟一:設(shè)置場景

voidRenderScene(void)

{

? ? //1.顏色值&光源位置

? ? staticGLfloatvLightPos [] = {1.0f,1.0f,0.0f};

? ? staticGLfloatvWhite [] = {1.0f,1.0f,1.0f,1.0f};


? ? //2.清理緩沖區(qū)

? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);


? ? //3.當(dāng)前模型視圖壓棧

? ? modelViewMatrix.PushMatrix();


? ? //添加照相機(jī)矩陣

? ? M3DMatrix44fmCamera;

? ? //從camraFrame中獲取一個(gè)4*4的矩陣

? ? cameraFrame.GetCameraMatrix(mCamera);

? ? //矩陣乘以矩陣堆棧頂部矩陣,相乘結(jié)果存儲(chǔ)到堆棧的頂部 將照相機(jī)矩陣 與 當(dāng)前模型矩陣相乘 壓入棧頂

? ? modelViewMatrix.MultMatrix(mCamera);


? ? //創(chuàng)建mObjectFrame矩陣

? ? M3DMatrix44fmObjectFrame;

? ? //從objectFrame中獲取矩陣,objectFrame保存的是特殊鍵位的變換矩陣

? ? objectFrame.GetMatrix(mObjectFrame);

? ? //矩陣乘以矩陣堆棧頂部矩陣,相乘結(jié)果存儲(chǔ)到堆棧的頂部 將世界變換矩陣 與 當(dāng)前模型矩陣相乘 壓入棧頂

? ? modelViewMatrix.MultMatrix(mObjectFrame);


? ? //4.綁定紋理,因?yàn)槲覀兊捻?xiàng)目中只有一個(gè)紋理。如果有多個(gè)紋理。綁定紋理很重要

? ? glBindTexture(GL_TEXTURE_2D, textureID);


? ? /*5.點(diǎn)光源著色器

?? ? 參數(shù)1:GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF(著色器標(biāo)簽)

?? ? 參數(shù)2:模型視圖矩陣

?? ? 參數(shù)3:投影矩陣

?? ? 參數(shù)4:視點(diǎn)坐標(biāo)系中的光源位置

?? ? 參數(shù)5:基本漫反射顏色

?? ? 參數(shù)6:圖形顏色(用紋理就不需要設(shè)置顏色。設(shè)置為0)

?? ? */

? ? shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetModelViewMatrix(),

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetProjectionMatrix(),

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? vLightPos, vWhite,0);


? ? //pyramidBatch 繪制

? ? pyramidBatch.Draw();


? ? //模型視圖出棧,恢復(fù)矩陣(push一次就要pop一次,push和pop成對(duì)存在)

? ? modelViewMatrix.PopMatrix();


? ? //6.交換緩存區(qū)

? ? glutSwapBuffers();

}

步驟二:繪制金字塔

voidMakePyramid(GLBatch& pyramidBatch)

{

? ? /*1、通過pyramidBatch組建三角形批次

? ? ? 參數(shù)1:類型

? ? ? 參數(shù)2:頂點(diǎn)數(shù)

? ? ? 參數(shù)3:這個(gè)批次中將會(huì)應(yīng)用1個(gè)紋理

? ? ? 注意:如果不寫這個(gè)參數(shù),默認(rèn)為0。

?? ? */

? ? pyramidBatch.Begin(GL_TRIANGLES,18,1);


? ? /***前情導(dǎo)入


?? ? 1)設(shè)置法線

?? ? void Normal3f(GLfloat x, GLfloat y, GLfloat z);

?? ? Normal3f:添加一個(gè)表面法線(法線坐標(biāo) 與 Vertex頂點(diǎn)坐標(biāo)中的Y軸一致)

?? ? 表面法線是有方向的向量,代表表面或者頂點(diǎn)面對(duì)的方向(相反的方向)。在多數(shù)的關(guān)照模式下是必須使用。后面的課程會(huì)詳細(xì)來講法線的應(yīng)用


?? ? pyramidBatch.Normal3f(X,Y,Z);


?? ? 2)設(shè)置紋理坐標(biāo)

?? ? void MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);

?? ? 參數(shù)1:texture,紋理層次,對(duì)于使用存儲(chǔ)著色器來進(jìn)行渲染,設(shè)置為0

?? ? 參數(shù)2:s:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的x坐標(biāo)

?? ? 參數(shù)3:t:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的y

?? ? (s,t,r,q對(duì)應(yīng)頂點(diǎn)坐標(biāo)的x,y,z,w)


?? ? pyramidBatch.MultiTexCoord2f(0,s,t);


?? ? 3)void Vertex3f(GLfloat x, GLfloat y, GLfloat z);

? ? ? void Vertex3fv(M3DVector3f vVertex);

?? ? 向三角形批次類添加頂點(diǎn)數(shù)據(jù)(x,y,z);

? ? ? pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);



?? ? 4)獲取從三點(diǎn)找到一個(gè)法線坐標(biāo)(三點(diǎn)確定一個(gè)面)

?? ? void m3dFindNormal(result,point1, point2,point3);

?? ? 參數(shù)1:結(jié)果

?? ? 參數(shù)2-4:3個(gè)頂點(diǎn)數(shù)據(jù)

?? ? */


? ? //塔頂

? ? M3DVector3fvApex = {0.0f,1.0f,0.0f};

? ? M3DVector3fvFrontLeft = { -1.0f, -1.0f,1.0f};

? ? M3DVector3fvFrontRight = {1.0f, -1.0f,1.0f};

? ? M3DVector3fvBackLeft = { -1.0f,? -1.0f, -1.0f};

? ? M3DVector3fvBackRight = {1.0f,? -1.0f, -1.0f};

? ? M3DVector3f n;


? ? //金字塔底部

? ? //底部的四邊形 = 三角形X + 三角形Y

? ? //三角形X = (vBackLeft,vBackRight,vFrontRight)


? ? //1.找到三角形X 法線

? ? m3dFindNormal(n, vBackLeft, vBackRight, vFrontRight);


? ? //vBackLeft

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackLeft);


? ? //vBackRight

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackRight);


? ? //vFrontRight

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontRight);



? ? //三角形Y =(vFrontLeft,vBackLeft,vFrontRight)


? ? //1.找到三角形X 法線

? ? m3dFindNormal(n, vFrontLeft, vBackLeft, vFrontRight);


? ? //vFrontLeft

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontLeft);


? ? //vBackLeft

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackLeft);


? ? //vFrontRight

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontRight);


? ? // 金字塔前面

? ? //三角形:(Apex,vFrontLeft,vFrontRight)

? ? m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);


? ? pyramidBatch.Normal3fv(n);

? ? pyramidBatch.MultiTexCoord2f(0,0.5f,1.0f);

? ? pyramidBatch.Vertex3fv(vApex);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontLeft);

? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontRight);


? ? //金字塔左邊

? ? //三角形:(vApex, vBackLeft, vFrontLeft)

? ? m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);

? ? pyramidBatch.Normal3fv(n);

? ? pyramidBatch.MultiTexCoord2f(0,0.5f,1.0f);

? ? pyramidBatch.Vertex3fv(vApex);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackLeft);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontLeft);


? ? //金字塔右邊

? ? //三角形:(vApex, vFrontRight, vBackRight)

? ? m3dFindNormal(n, vApex, vFrontRight, vBackRight);

? ? pyramidBatch.Normal3fv(n);

? ? pyramidBatch.MultiTexCoord2f(0,0.5f,1.0f);

? ? pyramidBatch.Vertex3fv(vApex);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vFrontRight);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackRight);


? ? //金字塔后邊

? ? //三角形:(vApex, vBackRight, vBackLeft)

? ? m3dFindNormal(n, vApex, vBackRight, vBackLeft);

? ? pyramidBatch.Normal3fv(n);

? ? pyramidBatch.MultiTexCoord2f(0,0.5f,1.0f);

? ? pyramidBatch.Vertex3fv(vApex);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackRight);


? ? pyramidBatch.Normal3fv(n);

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

? ? pyramidBatch.Vertex3fv(vBackLeft);


? ? //結(jié)束批次設(shè)置

? ? pyramidBatch.End();

}

步驟三:自定義函數(shù) ,從TGA文件加載2D紋理。

boolLoadTGATexture(constchar*szFileName,GLenumminFilter,GLenummagFilter,GLenumwrapMode)

{

? ? GLbyte*pBits;

? ? intnWidth, nHeight, nComponents;

? ? GLenumeFormat;


? ? //1、讀紋理位,讀取像素

? ? //參數(shù)1:紋理文件名稱

? ? //參數(shù)2:文件寬度地址

? ? //參數(shù)3:文件高度地址

? ? //參數(shù)4:文件組件地址

? ? //參數(shù)5:文件格式地址

? ? //返回值:pBits,指向圖像數(shù)據(jù)的指針


? ? pBits =gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);

? ? if(pBits ==NULL)

? ? ? ? return false;


? ? //2、設(shè)置紋理參數(shù)

? ? //參數(shù)1:紋理維度

? ? //參數(shù)2:為S/T坐標(biāo)設(shè)置模式

? ? //參數(shù)3:wrapMode,環(huán)繞模式

? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);

? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);


? ? //參數(shù)1:紋理維度

? ? //參數(shù)2:線性過濾

? ? //參數(shù)3:wrapMode,環(huán)繞模式

? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);

? ? glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);


? ? //3.載入紋理

? ? //參數(shù)1:紋理維度

? ? //參數(shù)2:mip貼圖層次

? ? //參數(shù)3:紋理單元存儲(chǔ)的顏色成分(從讀取像素圖是獲得)

? ? //參數(shù)4:加載紋理寬

? ? //參數(shù)5:加載紋理高

? ? //參數(shù)6:加載紋理的深度

? ? //參數(shù)7:像素?cái)?shù)據(jù)的數(shù)據(jù)類型(GL_UNSIGNED_BYTE,每個(gè)顏色分量都是一個(gè)8位無符號(hào)整數(shù))

? ? //參數(shù)8:指向紋理圖像數(shù)據(jù)的指針

? ? glTexImage2D(GL_TEXTURE_2D,0, nComponents, nWidth, nHeight,0,

?? ? ? ? ? ? ? ? eFormat,GL_UNSIGNED_BYTE, pBits);

? ? //使用完畢釋放pBits

? ? free(pBits);


? ? //4.加載Mip,紋理生成所有的Mip層

? ? //參數(shù):GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D

? ? glGenerateMipmap(GL_TEXTURE_2D);


? ? return true;

}

5、窗口改變監(jiān)聽

voidChangeSize(intw,inth)

{

? ? //1.設(shè)置視口

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

? ? //2.創(chuàng)建投影矩陣

? ? viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);

? ? //viewFrustum.GetProjectionMatrix()? 獲取viewFrustum投影矩陣

? ? //并將其加載到投影矩陣堆棧上

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


? ? //3.設(shè)置變換管道以使用兩個(gè)矩陣堆棧(變換矩陣modelViewMatrix ,投影矩陣projectionMatrix)

? ? //初始化GLGeometryTransform 的實(shí)例transformPipeline.通過將它的內(nèi)部指針設(shè)置為模型視圖矩陣堆棧 和 投影矩陣堆棧實(shí)例,來完成初始化

? ? //當(dāng)然這個(gè)操作也可以在SetupRC 函數(shù)中完成,但是在窗口大小改變時(shí)或者窗口創(chuàng)建時(shí)設(shè)置它們并沒有壞處。而且這樣可以一次性完成矩陣和管線的設(shè)置。

? ? transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

}

6、特殊鍵位操作

voidSpecialKeys(intkey,intx,inty)

{

? ? if(key ==GLUT_KEY_UP)

? ? ? ? objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);


? ? if(key == GLUT_KEY_DOWN)

? ? ? ? objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);


? ? if(key == GLUT_KEY_LEFT)

? ? ? ? objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);


? ? if(key == GLUT_KEY_RIGHT)

? ? ? ? objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);

? ? glutPostRedisplay();//視口改變,更新窗口

}

7、最后需要清除綁定的紋理

voidShutdownRC(void)

{

? ? glDeleteTextures(1, &textureID);

}

8、最終效果圖


圖8、最終效果圖


圖9,最終效果圖


[溪浣雙鯉的技術(shù)摸爬滾打之路](http://www.itdecent.cn/p/3fbecd65faae)

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、紋理基礎(chǔ) 3D圖形渲染中最基本的操作就是對(duì)一個(gè)表面應(yīng)用紋理。紋理可以表現(xiàn)只從網(wǎng)格的幾何形狀無法得到的附加細(xì)節(jié)。...
    cain_huang閱讀 9,170評(píng)論 0 7
  • 1 紋理基礎(chǔ) 紋理是一種結(jié)構(gòu)化的存儲(chǔ)形式(Textures are a structured form of st...
    RichardJieChen閱讀 16,550評(píng)論 0 10
  • 一、紋理綜述 物理世界中,視域內(nèi)的顏色會(huì)發(fā)生快速的變化。你可以看到很多物體表面都會(huì)呈現(xiàn)出豐富的顏色,并且在狹小的面...
    凡幾多閱讀 1,119評(píng)論 1 5
  • OpenGL: 紋理 1. 原始圖像數(shù)據(jù) 像素包裝圖像存儲(chǔ)空間 = 圖像width * 圖像height * 每個(gè)...
    Neal_f閱讀 1,359評(píng)論 0 2
  • http://blog.csdn.net/wangdingqiaoit/article/details/51457...
    jerryhigh閱讀 5,549評(píng)論 0 8

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