Cocos2d-x 3.0 紋理

1.紋理控制。程序員

Sprite *pSprite = Sprite::create("background.png");

TexParams params = {GL_NEAREST,GL_NEAREST,GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE};

pSprite->getTexture()->setTexParameters(params);

  上面最重要的函數就是setTexParameters();他就是根據ccTexParameters來控制紋理圖像的紋理如何對應到屏幕的像素。根據什麼來實現紋理的縮放和紋理的重複(重複紋理)等效果。ide

  /**
     Extension to set the Min / Mag filter
     */
    typedef struct _TexParams {
        GLuint    minFilter;//紋理過濾器:縮小過濾器
        GLuint    magFilter;//紋理過濾器:放大過濾器
        GLuint    wrapS;//橫向紋理尋址模式
        GLuint    wrapT;//縱向紋理尋址模式
    }TexParams;

先看看TexParams這個結構體,他的前兩個成員變量叫作基本過濾器。用來指定按照什麼規則來控制紋理的縮放效果。函數

兩個基本的紋理過濾規則:動畫

(1)GL_LINEAR:「當顯示紋理時,顯示的大小大於或者小於原紋理的尺寸時,使用鄰近像素點來插值補點」ui

     特色:圖像拉伸或者縮小後,看起來失真了,可是效果比GL_NEAREST好,看起來沒有人工操做後的痕跡.this

(2)GL_NEAREST:(最鄰近過濾)最簡單最快捷的過濾方式。spa

    特色:當紋理拉伸到特別大的時候,會出現大片斑駁狀像素。code

TexParameters後面的兩個成員變量叫作紋理環繞模式.是用來控制當繪製紋理邊界範圍以外的像素點的時候應該怎麼去處理。openGL紋理的座標範圍是(0.0f, 1.0f).意思就是當紋理座標大於1.0f或者紋理座標小於0.0f的時候怎麼去處理紋理。對象

兩個經常使用的紋理環繞模式:blog

(1)GL_REPEAT:在紋理超過1.0f的方向上對紋理進行重複。若是你想顯示紋理邊界以外的像素點時,把它旁邊的紋理像素點平鋪過去 .

    cocos2d::Texture2D::TexParams tp ;
    tp.minFilter = GL_LINEAR;
    tp.magFilter = GL_LINEAR;
    tp.wrapS = GL_REPEAT;
    tp.wrapT = GL_REPEAT;
    
    matteLayer=Sprite::create("middle_background.png");
    matteLayer->retain();

    matteLayer->setPosition(s.width/2,s.height/2);
    matteLayer->setScale(4.0f, 4.0f);
    matteLayer->getTexture()->setTexParameters(tp);
    
    
    this->addChild(matteLayer);
    
    this->schedule(schedule_selector(BackgroundLayer::changColor), 1.0f);
    
    this->schedule(schedule_selector(BackgroundLayer::scrollBackground), 0.01f);

在scrollBackground()中:

void BackgroundLayer::update(float dt){
  
    int nLen = 100;
    static int nOffset = 0;
    nOffset += nLen*dt;
    matteLayer->setTextureRect(Rect(0,-nOffset, matteLayer->getTexture()->getPixelsWide(),matteLayer->getTexture()->getPixelsHigh()));

}

上面的代碼經過不斷增長nOffset來繪製精靈的紋理邊界以外的區域。因爲以前設置了環繞模式爲GL_REPEAT。則繪製精靈以外的區域的時候把旁邊的紋理像素進行平鋪。造成重複紋理的效果。

程序中這個精靈的紋理不斷的會從右向左滾動。注意:精靈的位置不會發生變化.這就用GL_REPEAT來實現了重複紋理的效果.

還須要注意的是RepeatSprite.png的寬和高必須是2的N次方大小。不然的話當你用GL_REPEAT來做爲環繞模式的時候會出現警告提示:GL_REPEAT mode must be POT.意思就是用GL_REPEAT模式圖片大小必須是2的指數冪(POT).警告提示完了以後就是崩潰.

(2)GL_CLAMP:做用就是紋理的繪製座標大於1.0則就設置成1.0, 小於0.0則設置成0.0;

若是繪製的x座標大於了紋理寬度,則就用紋理最右邊的一個像素來繪製後面的區域.

2.紋理緩衝區.(TextureCache)

Sprite::create()這個函數裏面有句代碼:auto TexureCache=Director::getInstance()->getTextureCache();

 精靈就是用這句代碼來根據提供的圖片生成精靈的紋理對象。因此,不難看出用圖片建立了精靈對象時,圖片數據被加載到內存中,這塊內存就叫作紋理緩衝區(TextureCache),只要不手動就從紋理緩衝區中把圖片數據刪除則圖片數據永遠佔着內存不釋放。因此這就帶出了針對紋理緩衝區的一些議題.cocos2d中存放被加載的圖片數據的緩衝區(內存)分兩類:存放由多個小圖拼接成的大圖的區域   和  存放單個圖片的區域。具體分別對應於SpriteFrameCache和 TextureCache這兩個類。

爲何會存在這兩個類呢?從名字就知道他們是緩衝區,存在的惟一理由是下次若是須要同一個圖片數據的時候直接從緩衝區去取,而不須要再次把圖片文件載入到內存中去。這樣的話節省了內存還提升了渲染速度。

 

假設有一張圖片example.png被加載到緩衝區中去,若是這張圖片是第一次被加載到內存,則它首先被加載到緩衝區中去,而後再從緩衝區中讀取出來,用於建立紋理對象。

若是這個圖片的數據在內存中沒有被刪除,則在隨後程序員又想用圖片example.png來建立紋理對象的時候,cocos2d首先從紋理緩衝區中查找一下看是否存在這個圖片的數據。若是存在就直接從緩衝區中讀取。就不須要再次從硬盤載入到內存。多麼方便啦!難道不是嗎?這樣爲你節省了內存和提升了效率。 

釋放:

若是遊戲有不少場景,在切換場景的時候能夠把前一個場景的內存所有釋放,防止總內存太高.

Director::getInstance()->getTextureCache()->removeAllTextures(); 釋放到目前爲止全部加載的圖片

Director::getInstance()->getTextureCache()->removeUnusedTextures();將引用計數爲1的圖片釋放掉

Director::getInstance()->getTextureCache()->removeTexture();單獨釋放某個圖片

SpriteFrameCache 與 TextureCache 釋放的方法差很少。

值得注意的是釋放的時機,通常在切換場景的時候釋放資源,若是從A場景切換到B場景,調用的函數順序爲B::init()---->A::exit()---->B::onEnter() 可若是使用了切換效果,好比CTransitionJumpZoom::transitionWithDuration這樣的函數,則函數的調用順序變爲B::init()---->B::onEnter()---->A::exit() 並且第二種方式會有一瞬間將兩個場景的資源疊加在一塊兒,若是不採起過分,極可能會由於內存吃緊而崩潰。

有時強制釋放所有資源時,會使某個正在執行的動畫失去引用而彈出異常,能夠調用Director::getInstance()->getActionManager()->removeAllActions();來解決。

相關文章
相關標籤/搜索