(cocos2d-x) 背景模糊化以及效率優化
在遊戲中有時了為了突顯前景元素,需要對背景進行一些模糊化處理,如下圖所示
雖然cocos2d-x 3.x提供了新的使用者模糊化的shader指令碼,但根據實現方式的不同仍然會有很大區別。
方案0:對所有背景上所有精靈進行模糊化
最不可取的方案,多數情況下並不能達到預期效果,而且效率低,原因見以下兩圖:
第1張黑色背景是引擎示例中的效果,第2張是我在示例程式碼中加了一個白色背景後的效果。
這裡的問題是,實際上3.x版本提供shader指令碼無法很好的處理帶有透明度的圖片,由於示例預設都是黑色背景,因此無法看出問題,而在白色背景下,所有透明的地方都被處理成了黑色。相信現在遊戲中即使背景也會有大量帶有透明區域的圖片,況且當我們我們模糊處理的時候經常也需要處理前景圖片,那麼這個問題完全不能忽視了。
我本人對shader指令碼並不太熟悉,不過猜測應該可以靠修改shader指令碼解決。但即使如此,對場景中多個精靈進行模糊化,效率如何呢?我們來看方案1。
方案1:擷取螢幕生成一個精靈作為臨時背景,並對此精靈進行模糊化
基本思路是使用渲染到紋理技術生成一個臨時的圖片精靈,將此精靈置於場景最上層(即Zorder高於其他精靈),成為一個假背景,而把需要突顯的元素,再置於這個精靈之上。實現很容易,效果如圖:
粗略看貌似沒問題,但請注意左下角的幀率。實際上即使只對一個960x640尺寸的精靈進行模糊化,效率也非常低,長期保持在20幀以下。雖然這裡我的執行環境是整合顯示卡,這也是造成幀率的低的原因之一,但桌上型電腦尚且如此,移動裝置上很難表現的更好,況且移動裝置還要耗電和發熱問題,效率問題必須重視。於是便有了方案2。
方案2:用模糊化後的精靈生成一個普通精靈作為臨時背景
效果如圖:
幀數恢復到了60左右,經我在手機上測試,對1280x720的圖片進行這樣的處理,也幾乎沒有問題,僅僅會在生成模糊圖的一刻會瞬間降到40幀左右,之後會迅速恢復至60幀。
以下是實現程式碼:
#include "HelloWorldScene.h" USING_NS_CC; ////////////////////////////////////////////////////////////////////////// //精靈模糊類 ////////////////////////////////////////////////////////////////////////// class SpriteBlur : public cocos2d::Sprite { public: SpriteBlur(); ~SpriteBlur(); static SpriteBlur* create(cocos2d::Sprite* pSprite, const float fRadius = 8.0f, const float fSampleNum = 8.0f); bool initWithTexture(cocos2d::Texture2D* pTexture, const cocos2d::Rect& rRect); void initGLProgram(); void setBlurRadius(float fRadius); void setBlurSampleNum(float fSampleNum); protected: float fBlurRadius_; float fBlurSampleNum_; }; SpriteBlur::SpriteBlur() : fBlurRadius_(0.0f) , fBlurSampleNum_(0.0f) { } SpriteBlur::~SpriteBlur() { } SpriteBlur* SpriteBlur::create(cocos2d::Sprite* pSprite, const float fRadius, const float fSampleNum) { SpriteBlur* pRet = new (std::nothrow) SpriteBlur(); if (nullptr == pRet) return nullptr; pRet->fBlurRadius_ = fRadius; pRet->fBlurSampleNum_ = fSampleNum; if (pRet->initWithSpriteFrame(pSprite->getSpriteFrame())) pRet->autorelease(); else CC_SAFE_DELETE(pRet); return pRet; } bool SpriteBlur::initWithTexture(cocos2d::Texture2D* texture, const cocos2d::Rect& rect) { if (Sprite::initWithTexture(texture, rect)) { #if CC_ENABLE_CACHE_TEXTURE_DATA auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){ setGLProgram(nullptr); initGLProgram(); }); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); #endif initGLProgram(); return true; } return false; } void SpriteBlur::initGLProgram() { GLchar * fragSource = (GLchar*)cocos2d::String::createWithContentsOfFile( cocos2d::FileUtils::getInstance()->fullPathForFilename("shaders/blur.fsh").c_str())->getCString(); auto program = cocos2d::GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource); auto glProgramState = cocos2d::GLProgramState::getOrCreateWithGLProgram(program); setGLProgramState(glProgramState); auto size = getTexture()->getContentSizeInPixels(); getGLProgramState()->setUniformVec2("resolution", size); getGLProgramState()->setUniformFloat("blurRadius", fBlurRadius_); getGLProgramState()->setUniformFloat("sampleNum", fBlurSampleNum_); } void SpriteBlur::setBlurRadius(float radius) { fBlurRadius_ = radius; getGLProgramState()->setUniformFloat("blurRadius", fBlurRadius_); } void SpriteBlur::setBlurSampleNum(float num) { fBlurSampleNum_ = num; getGLProgramState()->setUniformFloat("sampleNum", fBlurSampleNum_); } ////////////////////////////////////////////////////////////////////////// //精靈模糊化函式 ////////////////////////////////////////////////////////////////////////// cocos2d::RenderTexture* SpriteBlurer(cocos2d::Sprite* pSprite, const float fRadius = 8.0f, const float fSampleNum = 8.0f) { //模糊化的臨時精靈 auto pSptBlur = SpriteBlur::create(pSprite, fRadius, fSampleNum); pSptBlur->setRotationSkewX(180.0f); pSptBlur->setPositionX(pSptBlur->getContentSize().width / 2); pSptBlur->setPositionY(pSptBlur->getContentSize().height / 2); //使用精靈尺寸初始化一個空的渲染紋理物件 cocos2d::RenderTexture* textureScreen = cocos2d::RenderTexture::create(pSptBlur->getContentSize().width, pSptBlur->getContentSize().height); //開始獲取 textureScreen->beginWithClear(0.0f, 0.0f, 0.0f, 0.0f); //遍歷節點物件,填充紋理到texure中 pSptBlur->visit(); //結束獲取 textureScreen->end(); return textureScreen; } ////////////////////////////////////////////////////////////////////////// //截圖函式 ////////////////////////////////////////////////////////////////////////// cocos2d::RenderTexture* ScreenShot(const bool bIsSave, std::function<void(cocos2d::RenderTexture*, const std::string&)> pFuncCallback) { //使用螢幕尺寸初始化一個空的渲染紋理物件 Size sizeWin = Director::getInstance()->getWinSize(); cocos2d::RenderTexture* textureScreen = cocos2d::RenderTexture::create(sizeWin.width, sizeWin.height); //清除資料並開始獲取 textureScreen->beginWithClear(0.0f, 0.0f, 0.0f, 0.0f); //遍歷場景節點物件,填充紋理到texure中 cocos2d::Director::getInstance()->getRunningScene()->visit(); //結束獲取 textureScreen->end(); //儲存為PNG圖 if (bIsSave) { static int s_iSerialNumber = 0; textureScreen->saveToFile( cocos2d::CCString::createWithFormat("ScreenShot_%04d.png", ++s_iSerialNumber)->getCString(), cocos2d::Image::Format::PNG, true, pFuncCallback); } else { if (nullptr != pFuncCallback) { pFuncCallback(textureScreen, ""); } } return textureScreen; } ////////////////////////////////////////////////////////////////////////// //示例 ////////////////////////////////////////////////////////////////////////// Scene* HelloWorld::createScene() { auto scene = Scene::create(); auto layer = HelloWorld::create(); scene->addChild(layer); return scene; } bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); auto menu = Menu::create(closeItem, NULL); menu->setPosition(Vec2::ZERO); this->addChild(menu, 1); auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24); label->setPosition(Vec2(origin.x + visibleSize.width/2, origin.y + visibleSize.height - label->getContentSize().height)); this->addChild(label, 1); auto sprite = Sprite::create("HelloWorld.png"); sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); this->addChild(sprite, 0); ////////////////////////////////////////////////////////////////////////// //背景模糊 ////////////////////////////////////////////////////////////////////////// //新增按鍵用於觸發背景模糊 auto blurItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", [&](Ref* pSender){ //擷取螢幕(不儲存圖片,不設定回撥函式) auto textureScreen = ScreenShot(false, nullptr); //方案1:直接對背景精靈進行模糊化操作(效率低) //使用擷取後獲得的截圖精靈,生成一個帶模糊效果的精靈 //SpriteBlur* spriteBlur = SpriteBlur::create(textureScreen->getSprite(), 8.0f, 8.0f); //spriteBlur->setRotationSkewX(180.0f); //方案2:將模糊化後的精靈儲存成一張圖片 //將擷取的螢幕進行模糊化 auto textureBlur = SpriteBlurer(textureScreen->getSprite()); //將模糊化後的圖片儲存成一張圖片 auto spriteBlur = Sprite::createWithSpriteFrame(textureBlur->getSprite()->getSpriteFrame()); spriteBlur->setPosition(Vec2(visibleSize.width, visibleSize.height)); Size size = Director::getInstance()->getWinSize(); spriteBlur->setRotationSkewX(180.0f); spriteBlur->setPosition(Vec2(size.width / 2, size.height / 2)); //將此精靈覆蓋在原有層之上,成為一個臨時背景 this->addChild(spriteBlur, 4); //新增一個新的圖片作為前景元素以便進行比較 auto sprite = Sprite::create("HelloWorld.png"); sprite->setPosition(Vec2(size.width / 2, size.height / 2)); sprite->setScale(0.5f); this->addChild(sprite, 5); } ); blurItem->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2)); menu->addChild(blurItem); return true; } void HelloWorld::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif }
HelloWorldScene.h未做任何修改,因此此處不再貼出。
class SpriteBlur用於生成可被shader處理的精靈,注意將cocos2d-x的shader指令碼拷入自己的專案中。得到的精靈每一幀都會進行畫素渲染,可以動態調節模糊效果。建構函式中的除了需要模糊化的精靈之外,另外兩個引數:fRadius為模糊半徑,此引數越大,模糊效果越明顯;fSampleNum為模糊取樣,此引數越大,模糊效果越細膩。這兩個引數越高,效率也就越低。並且當高過一定數值後,在手機上有可能出現異常,建議兩個引數設定均不要超過8。
ScreenShot為截圖函式,相關教程很多,此處不再展開。
SpriteBlurer為精靈模糊化函式,將一個普通精靈傳入,即可返回一個被模糊化處理後的紋理,使用此紋理即可生成普通精靈。即把用shader處理過的精靈截圖,生成普通精靈,此精靈不再需要進行畫素渲染,因此保證了效率。
相關推薦
(cocos2d-x) 背景模糊化以及效率優化
在遊戲中有時了為了突顯前景元素,需要對背景進行一些模糊化處理,如下圖所示 雖然cocos2d-x 3.x提供了新的使用者模糊化的shader指令碼,但根據實現方式的不同仍然會有很大區別。 方案0:對所有背景上所有精靈進行模糊化 最不可取的方案,多數情況下並不能達到預期效
Windows平臺cocos2d-x 3.2下載以及建立新專案過程
首先,有關於cocos2d-x在windows下Android環境的搭建, 這裡簡單列一下所需工具的下載地址: 1、JDK 下載地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 2
Cocos2d-x中Vector容器以及例項介紹
Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容納的是Ref及子類所建立的物件指標,其中的T是模板,表示能夠放入到容器中的型別,在Cocos2d-x 3.x中T表
如何實現Android 佈局背景模糊化處理
在模仿 IOS 密碼輸入頁面的時候發現其背景有模糊處理,於是瞭解了一下並記錄下來,以便使用.在Android 中具體實現方法如下查考 http://www.cnblogs.com/lipeil/p/3997992.htmlprivate void applyBlur() { // 獲取桌布管理器
SparkStreaming讀取kafka資料進行反序列化以及mapPartition優化例項
val monitorWrappedMessage1 = KafkaUtils.createStream[String, Array[Byte], StringDecoder, DefaultDecoder]( ssc, kafkaParams, topic
Cocos2d-x優化中關於背景圖片優化
指針 text .cpp 互動出版網 沒有 tde white 實現 origin 因為背景圖片長時間在場景中保存,並且圖片非常多,我們能夠對其進行一些優化。我們通過例如以下幾個方面考慮優化:1、不要Alpha通道背景圖片的特點是不須要透明的,所以紋理格式能夠採用不帶有A
UIKit和Cocos2d-x的整合使用;設定CCEAGLView背景為透明,來顯示背後的UIView; 以及整合中遇到的問題的解決方案
UIKit和Cocos2d-x的整合使用 原來我們的專案通過原始的UIKit來實現應用開發,但是現在需要往應用中增加禮物特效動畫,而禮物特效需要通過cocos2d-x來實現。晚上的方法大多都是通過建立初始的cocos2d工程,再在工程中增加UIKit的實現。最著名的介紹這個
Cocos2d-x中Vector<T>容器以及實例介紹
top 宋體 hello 操作符 模板類 log ins bsp main Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容納的是Ref及子類所創建的對象指針,其中的T是模板,表示能夠放入到容器中的類型,在Cocos2d-x 3.x
Cocos2d-x v3.1.1 創建以及編譯項目
耐心 以及 系統 content win 3.1 包名 安裝路徑 ont 1.安裝python, 並將安裝路徑增加系統環境變量中; 2. 執行cocos2d-x根文件夾下的setup.py; 3. 進入cmd, 輸入: cocos new 項目名稱 -p 包名 -l 語
quick-cocos2d-x教程9:實例之加上背景圖片
nbsp mod work .text eight zip function 大小 dto 在梳理完quick-cocos2d-x框架的各個文件夾後,我們開始我們的實例教程,在helloworld後面。加上一張圖片,lua編輯器,我用的lua editor。還不錯。
我學cocos2d-x (三) Node:一切可視化對象的祖先
父類 顯示 fine rtu cocos2 static trac 坐標 ati 在cocos2d-x中一切可視化的對象都繼承自Node(如文字(label)、精靈(sprite)、場景(scene)、布局(layer))。這是一個純虛類。主要負責決定元素顯示的位置
Cocos2d-x Lua遊戲開發Mac環境搭建以及一點點感悟
感覺 慢慢 怎樣 tid lease 人生 第三方 什麽 增強 接觸Cocos2d-x 最近由於公司項目的需要,自己開始接觸Cocos,開始做一些簡單的輕量級的遊戲,以前沒有接觸過這一塊的東西,也是借助這個機會學習一下遊戲的開發,由於以前自己
cocos2d-x 圖片紋理優化 資源加載方案
context 24* fad 對話 一個bug mipmap cocos 依靠 ast 原文地址:http://blog.sina.com.cn/s/blog_64d591e80101me1y.html 文章主要解決了我一直以來疑惑的幾個問題 1.到底用不用2的N次冪的圖
改善深層神經網路:超引數除錯、正則化以及優化_課程筆記_第一、二、三週
所插入圖片仍然來源於吳恩達老師相關視訊課件。仍然記錄一下一些讓自己思考和關注的地方。 第一週 訓練集與正則化 這周的主要內容為如何配置訓練集、驗證集和測試集;如何處理偏差與方差;降低方差的方法(增加資料量、正則化:L2、dropout等);提升訓練速度的方法:歸一化訓練集;如何合理的初始化權
吳恩達改善深層神經網路引數:超引數除錯、正則化以及優化——優化演算法
機器學習的應用是一個高度依賴經驗的過程,伴隨著大量的迭代過程,你需要訓練大量的模型才能找到合適的那個,優化演算法能夠幫助你快速訓練模型。 難點:機器學習沒有在大資料發揮最大的作用,我們可以利用巨大的資料集來訓練網路,但是在大資料下訓練網路速度很慢; 使用快速的優化演算法大大提高效率
改善深層神經網路:超引數除錯、正則化以及優化 優化演算法 第二週
改善深層神經網路:超引數除錯、正則化以及優化 優化演算法 第二課 1. Mini-batch Batch vs Mini-batch gradient descent Batch就是將所有的訓練資料都放到網路裡面進行訓練,計算量大,硬體要求高。一次訓練只能得到一個梯
吳恩達 改善深層神經網路:超引數除錯、正則化以及優化 第一週
吳恩達 改善深層神經網路:超引數除錯、正則化以及優化 課程筆記 第一週 深度學習裡面的實用層面 1.1 測試集/訓練集/開發集 原始的機器學習裡面訓練集,測試集和開發集一般按照6:2:2的比例來進行劃分。但是傳統的機器學習
cocos2d-x v3.0各個環境下建立專案以及編譯、執行官方DEMO
如何建立一個新專案 How to start a new game Runsetup.pyRun thecocosscriptExample: $ cd cocos2d-x $ ./setup.py $ source FILE_TO_SAVE_SYSTEM_VARIAB
Mysql模糊查詢like效率,以及更高效的寫法
原文來自:https://www.cnblogs.com/chaobest/p/6737901.html在使用msyql進行模糊查詢的時候,很自然的會用到like語句,通常情況下,在資料量小的時候,不容易看出查詢的效率,但在資料量達到百萬級,千萬級的時候,查詢的效率就很容易顯
吳恩達《深度學習-改善深層神經網路》3--超引數除錯、正則化以及優化
1. 系統組織超參除錯Tuning process1)深度神經網路的超參有學習速率、層數、隱藏層單元數、mini-batch大小、學習速率衰減、β(優化演算法)等。其重要性各不相同,按重要性分類的話: 第一類:最重要的引數就是學習速率α 第二類:隱藏層單元數、min