cocos2d-x 字体描边CCRenderTexture glBlendFunc

来源:互联网 发布:linux java cpu占用高 编辑:程序博客网 时间:2024/05/17 08:49
///////////////////////////////////
//author : zhxfl
//date   : 2013.3.1
//email  : 291221622@qq.com
//Adress : http://blog.sina.com.cn/s/blog_a502f1a30101hvh7.html
///////////////////////////////////
先上核心代码,基本的思路就是用黑色的同样轮廓的字体,向四周偏移一点,最后在把需要的字体叠加在画出来的轮廓上面。

void CCStrokeLabel::init()
{
    float strokeSize = getStrokeSize();
   // float fontSize = m_fontSize - 2 * strokeSize;
    CCLabelTTF *label = CCLabelTTF::labelWithString(
            m_str.c_str(), m_font.c_str(), m_fontSize);
    CCSize textureSize = label->getContentSize();
    textureSize.width += 2 * strokeSize;
    textureSize.height += 2 * strokeSize;
    //call to clear error
    glGetError();
    CCRenderTexture *rt = CCRenderTexture::renderTextureWithWidthAndHeight(
            textureSize.width, textureSize.height);
    if(!rt)
    {
        ERROR_MSG("create render texture failed !!!!");
        addChild(label);
        return;
    }

    label->setColor(ccc3(0, 0, 0));

    ccBlendFunc originalBlend = label->getBlendFunc();
    ccBlendFunc func = { GL_SRC_ALPHA, GL_ONE};
    label->setBlendFunc(func);

    label->setAnchorPoint(ccp(0.5, 0.5));

    rt->begin();
    for(int i = 0; i < 360; i += 15)
    {
        float r = CC_DEGREES_TO_RADIANS(i);
        label->setPosition(ccp(
                textureSize.width * 0.5f + sin(r) * strokeSize,
                textureSize.height * 0.5f + cos(r) * strokeSize));
        label->visit();
    }
    label->setColor(m_color);
    label->setBlendFunc(originalBlend);
    label->setPosition(ccp(textureSize.width * 0.5f, textureSize.height * 0.5f));
    label->visit();
    rt->end(false);

    CCTexture2D *texture = rt->getSprite()->getTexture();
    texture->setAliasTexParameters();
    m_sprite = CCSprite::spriteWithTexture(rt->getSprite()->getTexture());
    setContentSize(m_sprite->getContentSize());
    m_sprite->setAnchorPoint(ccp(0, 0));
    m_sprite->setPosition(ccp(0, 0));
    ((CCSprite *)m_sprite)->setFlipY(true);
    addChild(m_sprite);
}

这段代码主要是需要理解两个东西
1  openGl 颜色混合的方法glBlendFunc

OpenGL 会把源颜色和目标颜色各自取出,并乘以一个系数(源颜色乘以的系数称为“源因子”,目标颜色乘以的系数称为“目标因子”),然后相加,这样就得到了新的颜 色。(也可以不是相加,新版本的OpenGL可以设置运算方式,包括加、减、取两者中较大的、取两者中较小的、逻辑运算等,但我们这里为了简单起见,不讨 论这个了) 下面用数学公式来表达一下这个运算方式。假设源颜色的四个分量(指红色,绿色,蓝色,alpha值)是(Rs, Gs, Bs, As),目标颜色的四个分量是(Rd, Gd, Bd, Ad),又设源因子为(Sr, Sg, Sb, Sa),目标因子为(Dr, Dg, Db, Da)。则混合产生的新颜色可以表示为: (Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da) 当然了,如果颜色的某一分量超过了1.0,则它会被自动截取为1.0,不需要考虑越界的问题。
 
源因子和目标因子是可以通过glBlendFunc函数来进行设置的。glBlendFunc有两个参数,前者表示源因子,后者表示目标因子。这两个参数可以是多种值,下面介绍比较常用的几种。
 
GL_ZERO: 表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。
 
GL_ONE: 表示使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算。
 
GL_SRC_ALPHA:表示使用源颜色的alpha值来作为因子。
 
GL_DST_ALPHA:表示使用目标颜色的alpha值来作为因子。
 
GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。
 
GL_ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。 除此以外,还有GL_SRC_COLOR(把源颜色的四个分量分别作为因子的四个分量)、GL_ONE_MINUS_SRC_COLOR、 GL_DST_COLOR、GL_ONE_MINUS_DST_COLOR等,前两个在OpenGL旧版本中只能用于设置目标因子,后两个在OpenGL 旧版本中只能用于设置源因子。新版本的OpenGL则没有这个限制,并且支持新的GL_CONST_COLOR(设定一种常数颜色,将其四个分量分别作为 因子的四个分量)、GL_ONE_MINUS_CONST_COLOR、GL_CONST_ALPHA、 GL_ONE_MINUS_CONST_ALPHA。另外还有GL_SRC_ALPHA_SATURATE。新版本的OpenGL还允许颜色的alpha 值和RGB值采用不同的混合因子。
 
 
 
举例来说: 如果设置了glBlendFunc(GL_ONE, GL_ZERO);,则表示完全使用源颜色,完全不使用目标颜色,因此画面效果和不使用混合的时候一致(当然效率可能会低一点点)。如果没有设置源因子和目标因子,则默认情况就是这样的设置。 如果设置了glBlendFunc(GL_ZERO, GL_ONE);,则表示完全不使用源颜色,因此无论你想画什么,最后都不会被画上去了。(但这并不是说这样设置就没有用,有些时候可能有特殊用途) 如 果设置了glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);,则表示源颜色乘以自身的alpha 值,目标颜色乘以1.0减去源颜色的alpha值,这样一来,源颜色的alpha值越大,则产生的新颜色中源颜色所占比例就越大,而目标颜色所占比例则减 小。这种情况下,我们可以简单的将源颜色的alpha值理解为“不透明度”。这也是混合时最常用的方式。 如果设置了glBlendFunc(GL_ONE, GL_ONE);,则表示完全使用源颜色和目标颜色,最终的颜色实际上就是两种颜色的简单相加。例如红色(1, 0, 0)和绿色(0, 1, 0)相加得到(1, 1, 0),结果为黄色。
 
 
 
注意: 所 谓源颜色和目标颜色,是跟绘制的顺序有关的。假如先绘制了一个红色的物体,再在其上绘制绿色的物体。则绿色是源颜色,红色是目标颜色。如果顺序反过来,则 红色就是源颜色,绿色才是目标颜色。在绘制时,应该注意顺序,使得绘制的源颜色与设置的源因子对应,目标颜色与设置的目标因子对应。不要被混乱的顺序搞晕 。

CCRenderTexture 的用法
   这个类简单说其实就是画板,在begin()和end()之间visit的纹理,都会画在CCRenderTexture里面。画完之后,就可以将所画的东西生成一个CCSprite对象,形成一个新的图。
    rt->begin();
    //把需要画在RenderTexture里面的精灵全部
    rt->end(false);
原创粉丝点击