Shader笔记4-描边

    描边原理:在片段着色器里面,对于每个像素:1. 如果它是不透明的像素,则不管,维持原本颜色;2. 如果透明,是360度判断它四周有没有不透明的像素,如果有,则把它设成描边颜色,否则保持透明。

顶点着色器 Outline.vert

attribute vec4 a_position;

attribute vec2 a_texCoord;

attribute vec4 a_color;

//varying 顶点shader和片段shader之间相互传递的参数。

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设置的颜色

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; // 这个浮点数是 pi / 180,角度转弧度

    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()

{

     //先判断当前像素是否透明,如果不透明则直接返回。

    vec4 myC = texture2D(CC_Texture0, v_texCoord); // 正在处理的这个像素点的颜色

    if (myC.a >= 0.5) // 不透明,不管,直接返回

    {

        gl_FragColor = v_fragmentColor * myC;

        return;

     }

    //如果是透明像素,就判断这个点周围12个方向,每个方向距离当前像素距离是outlineSize的像素点是否透明,

    //只要有一个是非透明像素,就把当前像素点设为描边的颜色,并设置成非透明。

   int strokeCount = 0;

    for (int i = 0; i < 12; i++)

    {

            strokeCount += getIsStrokeWithAngel(i * 30);

    }

    if (strokeCount > 0) // 四周围至少有一个点是不透明的,这个点要设成描边颜色

    {

          myC.rgb = outlineColor;

          myC.a = 1.0;

    }

    gl_FragColor = v_fragmentColor * myC;

}

        先判断当前像素是否透明,如果不透明则直接返回。如果是透明像素,就判断这个点周围12个方向,每个方向距离当前像素距离是outlineSize的像素点是否透明,只要有一个是非透明像素,就把当前像素点设为描边的颜色,并设置成非透明。

使用示例

//精灵

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);

//设置属性

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));

效果

Shader笔记4-描边_第1张图片

你可能感兴趣的:(Shader笔记4-描边)