? ? 描邊原理:在片段著色器里面,對于每個像素:1. 如果它是不透明的像素矾踱,則不管,維持原本顏色疏哗;2. 如果透明呛讲,是360度判斷它四周有沒有不透明的像素,如果有返奉,則把它設(shè)成描邊顏色贝搁,否則保持透明。
頂點著色器 Outline.vert
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;
}
片段著色器Outline.frag
varying vec4 v_fragmentColor; // vertex shader傳入雷逆,setColor設(shè)置的顏色
varying vec2 v_texCoord; // 紋理坐標
uniform float outlineSize; // 描邊寬度,以像素為單位
uniform vec3 outlineColor; // 描邊顏色
uniform vec2 textureSize; // 紋理大形畚尽(寬和高)膀哲,為了計算周圍各點的紋理坐標往产,必須傳入它,因為紋理坐標范圍是0~1
// 判斷在這個角度上距離為outlineSize那一點是不是透明
int getIsStrokeWithAngel(float angel)
{
? ? int stroke = 0;
? ? float rad = angel * 0.01745329252; // 這個浮點數(shù)是 pi / 180某宪,角度轉(zhuǎn)弧度
? ? vec2 unit = 1.0 / textureSize.xy;//單位坐標
? ? vec2 offset = vec2(outlineSize * cos(rad) * unit.x, outlineSize * sin(rad) * unit.y); //偏移量
? ? float a = texture2D(CC_Texture0, v_texCoord + offset).a;
? ? if (a >= 0.5)// 我把alpha值大于0.5都視為不透明仿村,小于0.5都視為透明
? ? {
? ? ? ? stroke = 1;
? ? }
? ? return stroke;
}
void main()
{
? ? ?//先判斷當(dāng)前像素是否透明,如果不透明則直接返回兴喂。
? ? vec4 myC = texture2D(CC_Texture0, v_texCoord); // 正在處理的這個像素點的顏色
? ? if (myC.a >= 0.5) // 不透明蔼囊,不管,直接返回
? ? {
? ? ? ? gl_FragColor = v_fragmentColor * myC;
? ? ? ? return;
? ? ?}
? ? //如果是透明像素衣迷,就判斷這個點周圍12個方向畏鼓,每個方向距離當(dāng)前像素距離是outlineSize的像素點是否透明,
? ? //只要有一個是非透明像素壶谒,就把當(dāng)前像素點設(shè)為描邊的顏色滴肿,并設(shè)置成非透明。
? ?int strokeCount = 0;
? ? for (int i = 0; i < 12; i++)
? ? {
? ? ? ? ? ? strokeCount += getIsStrokeWithAngel(i * 30);
? ? }
? ? if (strokeCount > 0) // 四周圍至少有一個點是不透明的佃迄,這個點要設(shè)成描邊顏色
? ? {
? ? ? ? ? myC.rgb = outlineColor;
? ? ? ? ? myC.a = 1.0;
? ? }
? ? gl_FragColor = v_fragmentColor * myC;
}
? ? ? ? 先判斷當(dāng)前像素是否透明泼差,如果不透明則直接返回。如果是透明像素呵俏,就判斷這個點周圍12個方向堆缘,每個方向距離當(dāng)前像素距離是outlineSize的像素點是否透明,只要有一個是非透明像素普碎,就把當(dāng)前像素點設(shè)為描邊的顏色吼肥,并設(shè)置成非透明。
使用示例
//精靈
auto splash = Sprite::create("grossini.png");
splash->setPosition(100, 100);
this->addChild(splash, 1);
splash->setScale(3);
//vert:頂點著色器? frag:片段著色器
auto glprogram = GLProgram::createWithFilenames("Shaders/test/Outline.vert", "Shaders/test/Outline.frag");
auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
splash->setGLProgramState(glprogramstate);
//設(shè)置屬性
glprogramstate->setUniformFloat("outlineSize", 3); // 描邊寬度
//描邊顏色
Color3B outlineColor(0, 255, 0);
glprogramstate->setUniformVec3("outlineColor", Vec3(outlineColor.r / 255.0f, outlineColor.g / 255.0f, outlineColor.b / 255.0f));
//圖片紋理大小
glprogramstate->setUniformVec2("textureSize", Vec2(splash->getContentSize().width, splash->getContentSize().height));
效果