最近研究了一下CocosCreator的shader使用方法,並把自己學習期間寫的一些效果分享出來。
CocosCreator版本:v2.3.2
官方學習鏈接:Material 材質介紹、Effect介紹(官方文檔是最好的學習文檔,一定要反覆多看)
描邊效果
原理:1.判斷圖片中的某個點周圍8個點的alpha值。2.判斷某點是否處於圖片邊緣。
如上3圖就是給精靈換材質並選定自定義的Effect。
頂點着色器代碼不用修改。
片元着色器代碼如下:
CCProgram fs %{
precision highp float;
#include <alpha-test>
#include <cc-global>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
//cocos規定在shader中所有非sampler的uniform都應以block形式聲明
uniform InputData{
float outlineWidth; //外部程序輸入描邊寬度1-1.0。
};
//檢查pos點是否需要描邊
bool checkIsMakeOutline(vec2 pos){
//alpha檢測值
float alpha = 0.1;
vec4 color = texture(texture, pos);
if(color.a <= alpha || outlineWidth == 0.0)return false;
//檢測當前點周圍的8個點的alpha值
color = texture2D(texture, pos + vec2(0, outlineWidth));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(outlineWidth, outlineWidth));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(outlineWidth, 0));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(outlineWidth, -outlineWidth));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(0, -outlineWidth));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(-outlineWidth, -outlineWidth));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(-outlineWidth, 0));
if(color.a <= alpha)return true;
color = texture2D(texture, pos + vec2(-outlineWidth, outlineWidth));
if(color.a <= alpha)return true;
//當前點已是紋理邊緣
if(pos.x <= outlineWidth || pos.x >= 1.0 - outlineWidth)return true;
if(pos.y <= outlineWidth || pos.y >= 1.0 - outlineWidth)return true;
return false;
}
void main () {
vec4 o = vec4(1, 1, 1, 1);
#if USE_TEXTURE
o *= texture(texture, v_uv0);
#if CC_USE_ALPHA_ATLAS_TEXTURE
o.a *= texture2D(texture, v_uv0 + vec2(0, 0.5)).r;
#endif
#endif
o *= v_color;
ALPHA_TEST(o);
if(checkIsMakeOutline(v_uv0)){
//檢查到v_uv0點需要描邊,直接改變顏色值
o = vec4(1, 0, 0, 1);
}
gl_FragColor = o;
}
}%
註釋寫的很詳細,大家應該都看得懂。
運行效果圖如下:
如果大家描邊寬度在編輯器中顯示和運行起來的效果相差很大(這個坑,在論壇看了很多大神的帖子,才爬出來)。
主要原因:cocos運行的時候默認會自動合圖,合圖之後導致Effect中接收到的紋理uv座標不是單個圖的紋理座標,大概就是這個意思吧。
解決方法:取消單個圖自動合圖。