OpenGL紋理API

首先我們需要知道無論是OpenGL中的紋理文件(tga格式),還是日常開發(fā)所使用的的圖片(png等常見圖片格式),最終都會被解壓成位圖從而顯示在屏幕上。

圖像存儲空間

一個(gè)圖形在幀緩存區(qū)中的存儲空間,可以根據(jù)如下公式計(jì)算,

圖像存儲空間 = 圖像的高度 * 圖像寬度 * 每個(gè)像素的字節(jié)數(shù)

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

  • 像素存儲方式
//改變像素存儲方式
void glPixelStorei(GLenum pname, GLint param);
//恢復(fù)像素存儲方式
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)的排列請求,允許設(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ù)類型來存儲顏?分量,像素?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); // 指定寫?入的緩存
  • 載入紋理
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);
/*
* target:`GL_TEXTURE_1D`、`GL_TEXTURE_2D`、`GL_TEXTURE_3D`。
* level:指定所加載的mip貼圖層次。?般我們都把這個(gè)參數(shù)設(shè)置為0。
* internalformat:每個(gè)紋理單元中存儲多少顏?成分。
* 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ù):與我們在講glDrawPixels 函數(shù)對于的參數(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);
  • 插入替換紋理
void glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsize width);
void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yOffset, GLint x, GLint 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ù),形成新的紋理使用
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);

// x,y 在顏?緩存區(qū)中指定了開始讀取紋理數(shù)據(jù)的位置; 
// 緩存區(qū)?的數(shù)據(jù),是源緩存區(qū)通過glReadBuffer設(shè)置的。

紋理對象

  • 生成紋理對象
//使?函數(shù)分配紋理對象
//指定紋理對象的數(shù)量 和 指針(指針指向?個(gè)?符號整形數(shù)組,由紋理對象標(biāo)識符填充)。 
void glGenTextures(GLsizei n, GLuint * textTures);
//綁定紋理狀態(tài) //參數(shù)target:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
//參數(shù)texture:需要綁定的紋理對象
void glBindTexture(GLenum target, GLunit texture);
//刪除綁定紋理對象
//紋理對象 以及 紋理對象指針(指針指向?個(gè)?符號整形數(shù)組,由紋理對象標(biāo)識符填充)。
void glDeleteTextures(GLsizei n, GLuint *textures); //測試紋理對象是否有效
//如果texture是?個(gè)已經(jīng)分配空間的紋理對象,那么這個(gè)函數(shù)會返回GL_TRUE,否則會返回GL_FALSE。 
GLboolean glIsTexture(GLuint texture);
  • 設(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);
//參數(shù)1:target,指定這些參數(shù)將要應(yīng)?在那個(gè)紋理模式上,?如GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D。 
//參數(shù)2:pname,指定需要設(shè)置那個(gè)紋理參數(shù)
//參數(shù)3:param,設(shè)定特定的紋理參數(shù)的值
  • 設(shè)置過濾方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) //紋理縮?時(shí),使用鄰近過濾
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) //紋理放大時(shí),使?線性過濾

鄰近過濾(GL_NEAREST) VS 線性過濾(GL_LINEAR)

鄰近過濾(GL_NEAREST):

線性過濾(GL_LINEAR):

  • 設(shè)置環(huán)繞方式
//參數(shù)1:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D 
//參數(shù)2:GL_TEXTURE_WRAP_S、GL_TEXTURE_T、GL_TEXTURE_R,針對s,t,r坐標(biāo) 
//參數(shù)3:GL_REPEAT、GL_CLAMP、GL_CLAMP_TO_EDGE、GL_CLAMP_TO_BORDER
//GL_REPEAT:OpenGL 在紋理坐標(biāo)超過1.0的?方向上對紋理進(jìn)?重復(fù)。
//GL_CLAMP:所需的紋理單元取?紋理邊界或TEXTURE_BORDER_COLOR。
//GL_CLAMP_TO_EDGE環(huán)繞模式強(qiáng)制對范圍之外的紋理坐標(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);

環(huán)繞方式:

環(huán)繞方式效果:

  • 枚舉變量簡介
    像素格式:

像素?cái)?shù)據(jù)的數(shù)據(jù)類型:

  • 紋理坐標(biāo)

紋理坐標(biāo)是頂點(diǎn)的一種映射關(guān)系映射關(guān)系
頂點(diǎn)坐標(biāo): (x, y, z, w) 紋理坐標(biāo): (s, t, r, q)

2D紋理坐標(biāo)左下角為(0, 0),右上角為(1, 1)。

3D紋理坐標(biāo)(不常用):

紋理常見的使用流程

bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
      //1.分配紋理對象 參數(shù)1:紋理對象個(gè)數(shù),參數(shù)2:紋理對象指針
    glGenTextures(1, &textureID);
    //2.綁定紋理狀態(tài) 參數(shù)1:紋理狀態(tài)2D 參數(shù)2:紋理對象
    glBindTexture(GL_TEXTURE_2D, textureID);
      
      //3、讀紋理位,讀取像素
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    //參數(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;
    
    //4、設(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);

    //5.載入紋理
    //參數(shù)1:紋理維度
    //參數(shù)2:mip貼圖層次
    //參數(shù)3:紋理單元存儲的顏色成分(從讀取像素圖是獲得)
    //參數(shù)4:加載紋理寬
    //參數(shù)5:加載紋理高
    //參數(shù)6:加載紋理的深度
    //參數(shù)7:像素?cái)?shù)據(jù)的數(shù)據(jù)類型(GL_UNSIGNED_BYTE,每個(gè)顏色分量都是一個(gè)8位無符號整數(shù))
    //參數(shù)8:指向紋理圖像數(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常常用于對游戲進(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)
        //6.紋理生成所有的Mip層
        //參數(shù):GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
        glGenerateMipmap(GL_TEXTURE_2D);
 
    return true;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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