馬賽克原理
? ? ? 要實現(xiàn)馬賽克的效果蚪拦,需要把圖片一個相當大小的正方形區(qū)域用同一個點的顏色來表示,相當于將連續(xù)的顏色離散化驰贷,因此我們可以想到用取整的方法來離散顏色,但是在我們的圖片紋理坐標采樣時在0到1的連續(xù)范圍次兆,因此我們需要將紋理坐標轉換成實際大小的整數(shù)坐標锹锰,接下來要把圖像這個坐標量化離散,比如對于一個分辨率為256X256像素的圖片恃慧,馬賽克塊的大小為8X8像素,我們先得將紋理坐標乘以(256,256)使其映射到0到256的范圍彪薛,相當于一個整數(shù)代表一個像素怠蹂,再將紋理坐標取除以8之后取整,最后再將坐標乘以8易遣,除以256.重新映射回0到1的范圍嫌佑,但是紋理坐標已經是離散的豆茫,而非連續(xù)的歧强。
頂點著色器代碼
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
//varying 頂點shader和片段shader之間相互傳遞的參數(shù)摊册。
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main()
{
? ? ? ? gl_Position = CC_PMatrix * a_position;
? ? ? ? v_fragmentColor = a_color;
? ? ? ? v_texCoord = a_texCoord;
}
片段著色器
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
//宿主程序傳遞的值
uniform vec2 texSize;? ? //圖片紋理大小
uniform vec2 mosaicSize;? //馬賽克格子大小
void main()
{
? ? ? ? //得到當前紋理坐標相對圖像大小整數(shù)值
? ? ? ? vec2 intXY = vec2(v_texCoord.x * texSize.x, v_texCoord.y * texSize.y);
? ? ? ? //根據(jù)馬賽克塊大小進行取整
? ? ? ? vec2 XYMosaic = vec2(int(intXY.x / mosaicSize.x) * mosaicSize.x, int(intXY.y / mosaicSize.y) * mosaicSize.y);
? ? ? ? //把整數(shù)坐標轉換回紋理采樣坐標
? ? ? ? vec2 UVMosaic = vec2(XYMosaic.x / texSize.x, XYMosaic.y / texSize.y);
? ? ? ? gl_FragColor = texture2D(CC_Texture0, UVMosaic);
}
cocos2d-x代碼
在頭文件上添加聲明代碼
//public:
void onUpdate(float dt); ? ?//update 這里每幀調用?
cocos2d::GLProgramState* _glProgramState = nullptr;
float _timer = 0.0;
在源文件的init()函數(shù)里添加以下代碼
//精靈
auto splash = Sprite::create("HelloWorld.png");?
splash->setPosition(100, 100);
this->addChild(splash, 1);
//vert:頂點著色器? frag:片段著色器
auto glprogram = GLProgram::createWithFilenames("Mosaic.vert", "Mosaic.frag");
_glProgramState = GLProgramState::getOrCreateWithGLProgram(glprogram);
//設置屬性
//設置紋理大小
_glProgramState->setUniformVec2("texSize", Vec2(splash->getContentSize().width, splash->getContentSize().height));
_glProgramState->applyUniforms();
splash->setGLProgramState(_glProgramState);
_timer = 0.0;
//每幀刷新
schedule(schedule_selector(HelloWorld::onUpdate));
最后onUpdate()更新馬賽克
void HelloWorld::onUpdate(float dt)
{
? ? ? ? //更新馬賽克
? ? ? ? _timer += dt;
? ? ? ? float mskSzie = (sin(_timer) + 2.0) * 8;
? ? ? ? _glProgramState->setUniformVec2("mosaicSize", Vec2(mskSzie, mskSzie));
}
可以看到動態(tài)馬賽克效果
馬賽克效果變種
? ? ? 在網(wǎng)上查資料的過程中,也看到一些很有意思的馬賽克算法變種棋枕,例如圓形妒峦,蜂巢形等。下面推薦鏈接肯骇,有興趣的可以去了解。
http://www.voidcn.com/blog/panda1234lee/article/p-6147128.html
想要了解更多的shader效果可以看一個牛人的博客:
http://blog.csdn.net/panda1234lee/article/category/6347204/1