OpenGL學(xué)習(xí)之路(6.0) 基礎(chǔ)紋理

原始圖像數(shù)據(jù)

  • .像素包裝
    • 圖像存儲(chǔ)空間 = 圖像的?高度 * 圖像寬度 * 每個(gè)像素的字節(jié)數(shù)

認(rèn)識(shí)函數(shù)

  • 像素存儲(chǔ)方式

//改變像素存儲(chǔ)?式
void glPixelStorei(GLenum pname,GLint param);
//恢復(fù)像素存儲(chǔ)?式
void glPixelStoref(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é)邊界開始)
glPixelStorei(GL_UNPACK_ALIGNMENT,1);

  • 從顏?緩存區(qū)內(nèi)容作為像素圖直接讀取
    /*
        //參數(shù)1:x,矩形左下角的窗?坐標(biāo)
        //參數(shù)2:y,矩形左下角的窗口坐標(biāo)
        //參數(shù)3:width,矩形的寬,以像素為單位 
        //參數(shù)4:height,矩形的高蟆湖,以像素為單位
        //參數(shù)5:format,OpenGL 的像素格式宛裕,參考 表6-1 
        //參數(shù)6:type,解釋參數(shù)pixels指向的數(shù)據(jù)槽惫,告訴OpenGL 使?緩存區(qū)中的什么 數(shù)據(jù)類型來存儲(chǔ)顏?分量,像素?cái)?shù)據(jù)的數(shù)據(jù)類型骇钦,參考 表6-2
        //參數(shù)7:pixels,指向圖形數(shù)據(jù)的指針
    */
    void glReadPixels(GLint x,GLint y,GLSizei width,GLSizei
            height, GLenum format, GLenum type,const void * pixels);
    glReadBuffer(mode);—> 指定讀取的緩存
    glWriteBuffer(mode);—> 指定寫?入的緩存

  • 載入紋理

/**
    * target:`GL_TEXTURE_1D`宛渐、`GL_TEXTURE_2D`、`GL_TEXTURE_3D`眯搭。
    * Level:指定所加載的mip貼圖層次皇忿。?般我們都把這個(gè)參數(shù)設(shè)置為0。
    * internalformat:每個(gè)紋理單元中存儲(chǔ)多少顏色成分坦仍。
    * width鳍烁、height、depth參數(shù):指加載紋理的寬度繁扎、高度幔荒、深度糊闽。
    ==注意!== 這些值必須是2的整數(shù)次方。(這是因?yàn)镺penGL 舊版本上的遺留留下的一個(gè)要求爹梁。當(dāng)然現(xiàn)在已經(jīng)可以支持不是2的整數(shù)次方右犹。但是開發(fā)者們還是習(xí)慣使用以2的整數(shù)次方去設(shè)置這些參數(shù)。)
    * border參數(shù):允許為紋理理貼圖指定一個(gè)邊界寬度姚垃。
    * format念链、type、data參數(shù):與我們?cè)谥vglDrawPixels 函數(shù)對(duì)于的參數(shù)相同
*/

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

  • 更新紋理: 可以從顏色緩存區(qū)讀取一段紋理來插入或替換积糯,插入紋理也一樣
    
    /**
    * target:`GL_TEXTURE_1D`掂墓、`GL_TEXTURE_2D`、`GL_TEXTURE_3D`看成。
    * Level:指定所加載的mip貼圖層次君编。?般我們都把這個(gè)參數(shù)設(shè)置為0。
    * internalformat:每個(gè)紋理單元中存儲(chǔ)多少顏色成分川慌。
    * width吃嘿、height、depth參數(shù):指加載紋理的寬度梦重、高度兑燥、深度。
    ==注意!== 這些值必須是2的整數(shù)次方琴拧。(這是因?yàn)镺penGL 舊版本上的遺留留下的一個(gè)要求降瞳。當(dāng)然現(xiàn)在已經(jīng)可以支持不是2的整數(shù)次方。但是開發(fā)者們還是習(xí)慣使用以2的整數(shù)次方去設(shè)置這些參數(shù)艾蓝。)
    * border參數(shù):允許為紋理理貼圖指定一個(gè)邊界寬度力崇。
    * format、type赢织、data參數(shù):與我們?cè)谥vglDrawPixels 函數(shù)對(duì)于的參數(shù)相同
*/
    void glTexSubImage1D(GLenum target,GLint level,GLint xOffset,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,GLint
  zOffset,GLsizei width,GLsizei height,GLsizei depth,Glenum type,const GLvoid * data);

  • 插?替換紋理

    /**
        * target:`GL_TEXTURE_1D`亮靴、`GL_TEXTURE_2D`、`GL_TEXTURE_3D`于置。
        * Level:指定所加載的mip貼圖層次茧吊。?般我們都把這個(gè)參數(shù)設(shè)置為0。
        * internalformat:每個(gè)紋理單元中存儲(chǔ)多少顏色成分八毯。
        * width搓侄、height、depth參數(shù):指加載紋理的寬度话速、高度讶踪、深度。
        ==注意!== 這些值必須是2的整數(shù)次方泊交。(這是因?yàn)镺penGL 舊版本上的遺留留下的一個(gè)要求乳讥。當(dāng)然現(xiàn)在已經(jīng)可以支持不是2的整數(shù)次方柱查。但是開發(fā)者們還是習(xí)慣使用以2的整數(shù)次方去設(shè)置這些參數(shù)。)
        * border參數(shù):允許為紋理理貼圖指定一個(gè)邊界寬度云石。
        * format唉工、type、data參數(shù):與我們?cè)谥vglDrawPixels 函數(shù)對(duì)于的參數(shù)相同
    */
    void glCopyTexSubImage1D(GLenum target,GLint level,GLint xoffset,GLint x,GLint y,GLsizei
    width);
    void glCopyTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yOffset,GLint x,GL
     y,GLsizei width,GLsizei height);
    void glCopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yOffset,GLint
     zOffset,GLint x,GLint y,GLsizei width,GLsizei height);

  • 使?顏色緩存區(qū)加載數(shù)據(jù),形成新的紋理使?

    /**

        x,y 在顏?緩存區(qū)中指定了了開始讀取紋理數(shù)據(jù)的位置; 緩存區(qū)里的數(shù)據(jù)汹忠,是源緩存區(qū)通過glReadBuffer設(shè)置的淋硝。
    注意:不存在glCopyTextImage3D ,因?yàn)槲覀?法從2D 顏?緩存區(qū)中獲取體積 數(shù)據(jù)宽菜。

    */
    void glCopyTexImage1D(GLenum target,GLint level,GLenum
    internalformt,GLint x,GLint y,GLsizei width,GLint border);
    void glCopyTexImage2D(GLenum target,GLint level,GLenum
    internalformt,GLint x,GLint y,GLsizei width,GLsizei
    height,GLint border);

  • 紋理對(duì)象的設(shè)置和使用
    
    //步驟一:
    // 使?函數(shù)分配紋理對(duì)象
    //指定紋理對(duì)象的數(shù)量 和 指針(指針指向?個(gè)無符號(hào)整形數(shù)組谣膳,由紋理對(duì)象標(biāo)識(shí)符填充)。 
    void glGenTextures(GLsizei n,GLuint * textTures);
    //步驟二:
    //綁定紋理狀態(tài) 
    //參數(shù) target:GL_TEXTURE_1D赋焕、GL_TEXTURE_2D参歹、GL_TEXTURE_3D     //參數(shù)texture:需要綁定的紋理對(duì)象
    void glBindTexture(GLenum target,GLunit texture);
    
    //步驟三:
    //刪除綁定紋理對(duì)象
    //紋理對(duì)象 以及 紋理對(duì)象指針(指針指向一個(gè)無符號(hào)整形數(shù)組仰楚,由紋理對(duì)象標(biāo)識(shí)符填充)隆判。 
    void glDeleteTextures(GLsizei n,GLuint *textures);
    
    //步驟四:(可選)
    //測試紋理對(duì)象是否有效 
    //如果texture是?個(gè)已經(jīng)分配空間的紋理對(duì)象,那么這個(gè)函數(shù)會(huì)返回GL_TRUE,否則會(huì)返回GL_FALSE僧界。 
    GLboolean     glIsTexture(GLuint texture);

  • 設(shè)置紋理參數(shù)

/**通用函數(shù)
參數(shù)1:target,指定這些參數(shù)將要應(yīng)用在哪個(gè)紋理模式上侨嘀,比如GL_TEXTURE_1D、GL_TEXTURE_2D捂襟、GL_TEXTURE_3D咬腕。 
參數(shù)2:pname,指定需要設(shè)置哪個(gè)紋理參數(shù),相當(dāng)于設(shè)置哪個(gè)屬性葬荷,例如人的身高涨共、體重等屬性
參數(shù)3:param,設(shè)定特定的紋理參數(shù)的值
*/
glTexParameterf(GLenum target,GLenum pname,GLFloat param);
glTexParameteri(GLenum target,GLenum pname,GLint param);
glTexParameterfv(GLenum target,GLenum pname,GLFloat *param);
glTexParameteriv(GLenum target,GLenum pname,GLint *param);

image.png
  • 像素?cái)?shù)據(jù)類型,表示著在每一個(gè)分量占多少個(gè)單位


    image.png
  • 設(shè)置過濾?式
    • 過濾方式分兩種
    • 一種是鄰近過濾(Nearest Neighbor Filtering):左上角那個(gè)紋理像素的中心距離紋理坐標(biāo)最近宠漩,所以它會(huì)被選擇為樣本顏色:


      image.png
- 一種是線性過濾(linear Filtering):它會(huì)基于紋理坐標(biāo)附近的紋理像素举反,計(jì)算出一個(gè)插值,近似出這些紋理像素之間的顏色扒吁。
image.png
- 2種紋理過濾?式比較
image.png
  • 過濾方式的使用
    //紋理縮小時(shí),使?鄰近過濾
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST) 
    //紋理放大時(shí),使用線性過濾
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR) 

  • 建議是紋理放大時(shí)用線性過濾火鼻,縮小時(shí)用鄰近過濾,但是僅僅是建議雕崩,也可以如下面那樣使用

    /**
    可以根據(jù)當(dāng)前需求來設(shè)置用鄰近過濾或者線性過濾
    */
                                            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_HEAREST);
                                              glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_HEAREST);
                                                    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
                                                    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

  • 設(shè)置環(huán)繞?式


    image.png
image.png
  • 環(huán)繞方式的函數(shù)使用

/**
    參數(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分別表示x鹏控,y冬念,z 坐標(biāo))
    參數(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范圍之外的只使用邊界紋理單元瀑构。邊界紋理單元是作為圍繞基本圖像的額外的?和列裆针,并與基本紋理圖像?起加載的。
*/
glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_S,GL_CLAMP_TO_EDGE);
glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_T,GL_CLAMP_TO_EDGE);

紋理坐標(biāo)

為了能夠把紋理映射(Map)到三角形上寺晌,我們需要指定三角形的每個(gè)頂點(diǎn)各自對(duì)應(yīng)紋理的哪個(gè)部分世吨。這樣每個(gè)頂點(diǎn)就會(huì)關(guān)聯(lián)著一個(gè)紋理坐標(biāo)(Texture Coordinate),用來標(biāo)明該從紋理圖像的哪個(gè)部分采樣(譯注:采集片段顏色)呻征。之后在圖形的其它片段上進(jìn)行片段插值(Fragment Interpolation)耘婚。

紋理坐標(biāo)在x和y軸上,范圍為0到1之間(注意我們使用的是2D紋理圖像)陆赋。使用紋理坐標(biāo)獲取紋理顏色叫做采樣(Sampling)沐祷。紋理坐標(biāo)起始于(0, 0),也就是紋理圖片的左下角攒岛,終始于(1, 1)赖临,即紋理圖片的右上角。下面的圖片展示了我們是如何把紋理坐標(biāo)映射到三角形上的灾锯。


image.png

我們?yōu)槿切沃付?個(gè)紋理坐標(biāo)點(diǎn)兢榨。如上圖所示,我們希望三角形的左下角對(duì)應(yīng)紋理的左下角顺饮,因此我們把三角形左下角頂點(diǎn)的紋理坐標(biāo)設(shè)置為(0, 0)吵聪;三角形的上頂點(diǎn)對(duì)應(yīng)于圖片的上中位置所以我們把它的紋理坐標(biāo)設(shè)置為(0.5, 1.0);同理右下方的頂點(diǎn)設(shè)置為(1, 0)兼雄。我們只要給頂點(diǎn)著色器傳遞這三個(gè)紋理坐標(biāo)就行了吟逝,接下來它們會(huì)被傳片段著色器中,它會(huì)為每個(gè)片段進(jìn)行紋理坐標(biāo)的插值君旦。

紋理坐標(biāo)看起來就像這樣:


GLfloat texCoords[] = {
    0.0f, 0.0f, // 左下角
    1.0f, 0.0f, // 右下角
    0.5f, 1.0f // 上中
};

對(duì)紋理采樣的解釋非常寬松澎办,它可以采用幾種不同的插值方式。所以我們需要自己告訴OpenGL該怎樣對(duì)紋理采樣金砍。

那么3D紋理坐標(biāo)是怎樣的呢局蚀?

  • 3D紋理坐標(biāo)圖形


    image.png

圖中問號(hào)坐標(biāo)位置是什么呢?答案是(1,1,0),為什么呢恕稠?請(qǐng)參考上面的2D紋理坐標(biāo)三角形了解

案例金字塔圖形解析

image.png

紋理坐標(biāo)請(qǐng)參考下面


image.png

紋理坐標(biāo)可以倒轉(zhuǎn)過來(意思就是(0,0) 與(0.1)互換位置琅绅,即是下圖打勾的連接方式),但是不可交叉連接鹅巍,像下圖那樣的交叉是不允許的


image.png

案例示例


#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;
GLFrame             cameraFrame;
GLFrame             objectFrame;
GLFrustum           viewFrustum;

GLBatch             pyramidBatch;

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

GLGeometryTransform transformPipeline;
M3DMatrix44f        shadowMatrix;

//繪制金字塔
void MakePyramid(GLBatch& pyramidBatch)
{
    /*1料祠、通過pyramidBatch組建三角形批次
     參數(shù)1:類型
     參數(shù)2:頂點(diǎn)數(shù)(金字塔是18個(gè)頂點(diǎn))
     參數(shù)3:這個(gè)批次中將會(huì)應(yīng)用1個(gè)紋理
     注意:如果不寫這個(gè)參數(shù),默認(rèn)為0澎羞。
     */
    pyramidBatch.Begin(GL_TRIANGLES, 18, 1);
    
    //金字塔底部
    //底部的四邊形 = 三角形X + 三角形Y
    //三角形X
    
    /*設(shè)置法線
     Normal3f:添加一個(gè)表面法線(法線坐標(biāo) 與 Vertex頂點(diǎn)坐標(biāo)中的Y軸一致)
     表面法線是有方向的向量髓绽,代表表面或者頂點(diǎn)面對(duì)的方向(相反的方向)。在多數(shù)的關(guān)照模式下是必須使用妆绞。
     */
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    
    /**設(shè)置紋理坐標(biāo)
     MultiTexCoord2f(GLuint texture,GLclampf s,GLclamp t);
     參數(shù)1:texture顺呕,紋理層次,對(duì)于使用存儲(chǔ)著色器來進(jìn)行渲染括饶,設(shè)置為0
     參數(shù)2:(s,t,r,q對(duì)應(yīng)頂點(diǎn)坐標(biāo)的x,y,z,w)s:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的x坐標(biāo)
     參數(shù)3:t:對(duì)應(yīng)頂點(diǎn)坐標(biāo)中的y
     */
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f); //可以看坐標(biāo)圖就明白了
    //vBlackLeft點(diǎn)
    pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
    //vBlackRight點(diǎn)
    pyramidBatch.Vertex3f(1.0f, -1.0f, -1.0f);
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    //vFrontRight點(diǎn)
    pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);
    
    
    //三角形B
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
    pyramidBatch.Vertex3f(-1.0f, -1.0f, 1.0f);
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
    pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
    pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
    pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
    pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);
    
    //塔頂
    M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };
    M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };
    M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };
    M3DVector3f vBackLeft = { -1.0f, -1.0f, -1.0f };
    M3DVector3f vBackRight = { 1.0f, -1.0f, -1.0f };
    M3DVector3f n;
    
    
    // 金字塔前面
    //三角形:(Apex株茶,vFrontLeft,vFrontRight)
    //紋理坐標(biāo)設(shè)置图焰,參考PPT圖6-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ù)
     */
    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();
    
}

// 將TGA文件加載為2D紋理启盛。
bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    
    //1、讀紋理位置技羔,讀取像素
    /**
     參數(shù)一:紋理文件名稱
     參數(shù)二:文件寬度地址
     參數(shù)三:文件高度地址
     參數(shù)四:文件組建地址
     參數(shù)五:文件格式地址
     返回值: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棍厂、精密包裝像素?cái)?shù)據(jù)
    //參數(shù)1:GL_UNPACK_ALIGNMENT,指定OpenGL如何從數(shù)據(jù)緩存區(qū)中解包圖像數(shù)據(jù)
    //參數(shù)2:針對(duì)GL_UNPACK_ALIGNMENT 設(shè)置的值
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    //載入紋理
    //參數(shù)1:紋理維度
    //參數(shù)2:mip貼圖層次,為0颗味,因?yàn)橹挥幸粚樱◤?開始)
    //參數(shù)3:紋理單元存儲(chǔ)的顏色成分(從讀取像素圖是獲得)
    //參數(shù)4:加載紋理寬
    //參數(shù)5:加載紋理高
    //參數(shù)6:加載紋理的深度
    //參數(shù)7:文件格式地址
    //參數(shù)8:像素?cái)?shù)據(jù)的數(shù)據(jù)類型(GL_UNSIGNED_BYTE超陆,每個(gè)顏色分量都是一個(gè)8位無符號(hào)整數(shù))
    //參數(shù)9:指向紋理圖像數(shù)據(jù)的指針
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);
    
    
    //使用完畢釋放pBits
    free(pBits);
    
    //只有minFilter 等于以下四種模式,才可以生成Mip貼圖
    //GL_NEAREST_MIPMAP_NEAREST具有非常好的性能浦马,并且閃爍現(xiàn)象非常弱
    //GL_LINEAR_MIPMAP_NEAREST常常用于對(duì)游戲進(jìn)行加速时呀,它使用了高質(zhì)量的線性過濾器
    //GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 過濾器在Mip層之間執(zhí)行了一些額外的插值,以消除他們之間的過濾痕跡晶默。
    //GL_LINEAR_MIPMAP_LINEAR 三線性Mip貼圖谨娜。紋理過濾的黃金準(zhǔn)則,具有最高的精度磺陡。
    if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
        
        //加載Mip,紋理生成所有的Mip層
        //參數(shù):GL_TEXTURE_1D趴梢、GL_TEXTURE_2D、GL_TEXTURE_3D
        glGenerateMipmap(GL_TEXTURE_2D);
    

    return true;
}


//初始化數(shù)據(jù)币他,設(shè)置基礎(chǔ)屬性
void SetupRC()
{
    //設(shè)置顏色
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
    
    //初始化著色器管理器
    shaderManager.InitializeStockShaders();
    
    //開啟深度測試
    glEnable(GL_DEPTH_TEST);
    
    //分配紋理對(duì)象
    /**
     參數(shù)1:紋理對(duì)象個(gè)數(shù)
     參數(shù)2:紋理對(duì)象指針
     */
    glGenTextures(1, &textureID);
    //綁定紋理狀態(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)繞模式 GL_CLAMP_TO_EDGE :超出的坐標(biāo)為用戶指定的邊緣顏色坞靶。
     */
    LoadTGATexture("stone.tga", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, GL_CLAMP_TO_EDGE);
    
    //創(chuàng)造金字塔pyramidBatch
    MakePyramid(pyramidBatch);
    
    /**相機(jī)frame MoveForward(平移)
     參數(shù)1:Z,深度(屏幕到圖形的Z軸距離)
     */
    cameraFrame.MoveForward(-10);
}



// 清理…例如刪除紋理對(duì)象
void ShutdownRC(void)
{
    glDeleteTextures(1, &textureID);
}


//開始渲染
void RenderScene(void)
{
    //顏色值 光照效果顏色蝴悉,圖形顏色
    static GLfloat vLightPos[] = { 1.0f, 1.0f, 0.0f };
    static GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 1.0f};
    
    //清理緩存區(qū)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    //當(dāng)前模型視頻壓棧
    modelViewMatrix.PushMatrix();
    //添加照相機(jī)矩陣
    M3DMatrix44f mCamera;
    //從camraFrame中獲取一個(gè)4*4的矩陣
    cameraFrame.GetCameraMatrix(mCamera);
    //矩陣乘以矩陣堆棧頂部矩陣彰阴,相乘結(jié)果存儲(chǔ)到堆棧的頂部 將照相機(jī)矩陣 與 當(dāng)前模型矩陣相乘 壓入棧頂
    modelViewMatrix.MultMatrix(mCamera);
    
    //創(chuàng)建mObjectFrame矩陣
    M3DMatrix44f mObjectFrame;
    //從objectFrame中獲取矩陣,objectFrame保存的是特殊鍵位的變換矩陣
    objectFrame.GetMatrix(mObjectFrame);
    //矩陣乘以矩陣堆棧頂部矩陣拍冠,相乘結(jié)果存儲(chǔ)到堆棧的頂部 將世界變換矩陣 與 當(dāng)前模型矩陣相乘 壓入棧頂
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    //為了確保防止其他地方修改該紋理尿这,所以再次綁定一次
    //綁定紋理簇抵,因?yàn)槲覀兊捻?xiàng)目中只有一個(gè)紋理。如果有多個(gè)紋理射众。綁定紋理很重要
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    /**點(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ù)矩陣
    modelViewMatrix.PopMatrix();
    
    //交換緩存區(qū)
    glutSwapBuffers();
}



void SpecialKeys(int key, int x, int y)
{
    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();
}


void ChangeSize(int w, int h)
{
    glViewport(0, 0, w, h);
    
    //創(chuàng)建投影矩陣
    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 500.0f);
    
    //viewFrustum.GetProjectionMatrix()  獲取viewFrustum投影矩陣
    //并將其加載到投影矩陣堆棧上
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    // 設(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);
}


int main(int argc, 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));
        return 1;
    }
    
    
    SetupRC();
    
    glutMainLoop();
    
    ShutdownRC();
    
    return 0;
}


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栖博,隨后出現(xiàn)的幾起案子屑宠,更是在濱河造成了極大的恐慌,老刑警劉巖仇让,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件典奉,死亡現(xiàn)場離奇詭異,居然都是意外死亡丧叽,警方通過查閱死者的電腦和手機(jī)卫玖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踊淳,“玉大人假瞬,你說我怎么就攤上這事∮爻ⅲ” “怎么了脱茉?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長垄开。 經(jīng)常有香客問我琴许,道長,這世上最難降的妖魔是什么溉躲? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任榜田,我火速辦了婚禮,結(jié)果婚禮上锻梳,老公的妹妹穿的比我還像新娘箭券。我一直安慰自己,他們只是感情好唱蒸,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布邦鲫。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庆捺。 梳的紋絲不亂的頭發(fā)上古今,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音滔以,去河邊找鬼捉腥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛你画,可吹牛的內(nèi)容都是我干的啊研。 我是一名探鬼主播屑埋,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了矫废?” 一聲冷哼從身側(cè)響起腾供,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤澳窑,失蹤者是張志新(化名)和其女友劉穎钠怯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凭迹,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡罚屋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嗅绸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脾猛。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鱼鸠,靈堂內(nèi)的尸體忽然破棺而出猛拴,到底是詐尸還是另有隱情,我是刑警寧澤瞧柔,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布漆弄,位于F島的核電站,受9級(jí)特大地震影響造锅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜廉邑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一哥蔚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛛蒙,春花似錦糙箍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春咕晋,著一層夾襖步出監(jiān)牢的瞬間雹拄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工掌呜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滓玖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓质蕉,卻偏偏與公主長得像势篡,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子模暗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 本文首發(fā)于個(gè)人博客:Lam's Blog - 【OpenGL-ES】二維紋理禁悠,文章由MarkDown語法編寫,可能...
    格子林ll閱讀 3,789評(píng)論 0 9
  • 版本記錄 前言 OpenGL 圖形庫項(xiàng)目中一直也沒用過兑宇,最近也想學(xué)著使用這個(gè)圖形庫绷蹲,感覺還是很有意思,也就自然想著...
    刀客傳奇閱讀 8,870評(píng)論 0 8
  • 1 紋理基礎(chǔ) 紋理是一種結(jié)構(gòu)化的存儲(chǔ)形式(Textures are a structured form of st...
    RichardJieChen閱讀 15,886評(píng)論 0 9
  • 紋理(Textures) 我們已經(jīng)了解到顾孽,我們可以為每個(gè)頂點(diǎn)使用顏色來增加圖形的細(xì)節(jié)祝钢,從而創(chuàng)建出有趣的圖像。但是通...
    IceMJ閱讀 5,642評(píng)論 2 13
  • 莉芙特悄悄靠近傳來講話聲的地方若厚。溫達(dá)說:“盡量別死得太慘拦英,主人。千萬不要開膛破肚测秸,輕輕拍一下腦袋就好疤估。” 那絕對(duì)是...
    Botanica閱讀 986評(píng)論 2 11