由于Cocos2d-x 2.x版本对描边支持的不好,3.X的基于Freetype的字库的描边效果还是不错的,但项目用的是旧版本引擎,又需要用到描边字,最近也研究了几种描边的方法,想分享一下。
在网上找了很多种描边的方式,各有优劣,有的描边效果很不错,而有的效果稍差但绘制效率更高。这篇文章讲解其中一种基于Shader的描边方法。
“云风”大哥的ejoy2d引擎中提供了一种效率很高的描边算法,使用ejoy2d进行描边时,有不错的效果,但是我集成到了cocos2dx中,描边效果不太明显,可能是与生成的纹理有关系,如果对描边的效果要求不高,可以考虑用一下这个描边效果。
描边的原理参考云风的博客,http://blog.codingnow.com/2013/09/edge_font.html
参考的ejoy2d的描边shader,可以去github上查看源码,https://github.com/ejoy/ejoy2d
描边shader如下:
/* * liCENSE ??? */#ifdef GL_ESprecision highp float;#endifuniform sampler2D u_texture;varying vec2 v_texCoord;varying vec4 v_fragmentcolor;uniform vec4 u_effectcolor;voID main() { float c = texture2D(u_texture,v_texCoord).w; float Alpha = clamp(c,0.0,0.5) * 2.0; float color = (clamp(c,0.5,1.0) - 0.5) * 2.0; gl_Fragcolor.xyz = (v_fragmentcolor.xyz + u_effectcolor.xyz) * color; gl_Fragcolor.w = Alpha; gl_Fragcolor *= v_fragmentcolor.w; gl_Fragcolor *= v_fragmentcolor.w; }
我封装了一个strokeLabel类来对cocos2dx的cclabelTTF进行了绘制的修改,增加了使用自有的shader进行着色的逻辑。
//// strokeLabel.h// strokeLabel_01//// Created by cc on 15/1/27.////#ifndef __strokeLabel_01__strokeLabel__#define __strokeLabel_01__strokeLabel__#include "cclabelTTFLoader.h"USING_NS_CC;class strokeLabel : public cclabelTTF { private: //描边宽度 float m_strokeSize; //描边效果颜色 cccolor4B m_effectcolor; cccolor4F m_effectcolorF; //文本颜色 cccolor4F m_textcolorF; cccolor4B m_textcolor; //描边颜色值,传入shader的全局变量 gluint m_uniformEffectcolor; public: #pragma mark <构造 && 析构> strokeLabel(); ~strokeLabel(); #pragma mark <创建 && 初始化> /** * 创建描边字 * * @param content 文本内容 * @param Fontname 字体 * @param FontSize 字号 * @param textcolor 文本颜色 * @param strokecolor 描边颜色 * @param strokeSize 描边宽度 * * @return 描边字 */ static strokeLabel* createWithAttribute(const std::string& content,const std::string& Fontname,float FontSize,const cccolor3B& textcolor,const cccolor3B& strokecolor,float strokeSize); /** * 初始化描边字 * * @param content 文本内容 * @param Fontname 字体 * @param FontSize 字号 * @param textcolor 文本颜色 * @param strokecolor 描边颜色 * @param strokeSize 描边宽度 * * @return true: 初始化成功 false: 初始化失败 */ bool initWithAttribute(const std::string& content,float strokeSize); /** * 更新Shader程序 */ voID updateShaderProgram(); /** * 绘制 */ virtual voID draw();};#endif /* defined(__strokeLabel_01__strokeLabel__) */
//// strokeLabel.cpp// strokeLabel_01//// Created by cc on 15/1/27.////#include "strokeLabel.h"strokeLabel::strokeLabel(): m_strokeSize(0),m_uniformEffectcolor(0) { }strokeLabel::~strokeLabel() { }long long int getNowTime() { struct timeval tv; gettimeofday(&tv,NulL); long long int NowTime = ((long long int)tv.tv_sec) * 1000 + tv.tv_usec / 1000; return NowTime;}/** * 创建描边字 * * @param content 文本内容 * @param Fontname 字体 * @param FontSize 字号 * @param textcolor 文本颜色 * @param strokecolor 描边颜色 * @param strokeSize 描边宽度 * * @return 描边字 */strokeLabel* strokeLabel::createWithAttribute(const std::string& content,float strokeSize) { strokeLabel *pRet = new strokeLabel(); if (pRet && pRet->initWithAttribute(content,Fontname,FontSize,textcolor,strokecolor,strokeSize)) { pRet->autorelease(); return pRet; } CC_SAFE_DELETE(pRet); return NulL;}/** * 初始化描边字 * * @param content 文本内容 * @param Fontname 字体 * @param FontSize 字号 * @param textcolor 文本颜色 * @param strokecolor 描边颜色 * @param strokeSize 描边宽度 * * @return true: 初始化成功 false: 初始化失败 */bool strokeLabel::initWithAttribute(const std::string& content,float strokeSize) { if (!cclabelTTF::initWithString(content.c_str(),Fontname.c_str(),FontSize)) { return false; } m_textcolor = ccc4(textcolor.r,textcolor.g,textcolor.b,255); m_textcolorF.r = m_textcolor.r / 255.0f; m_textcolorF.g = m_textcolor.g / 255.0f; m_textcolorF.b = m_textcolor.b / 255.0f; m_textcolorF.a = m_textcolor.a / 255.0f; m_effectcolor = ccc4(strokecolor.r,strokecolor.g,strokecolor.b,255);; m_effectcolorF.r = m_effectcolor.r / 255.0f; m_effectcolorF.g = m_effectcolor.g / 255.0f; m_effectcolorF.b = m_effectcolor.b / 255.0f; m_effectcolorF.a = m_effectcolor.a / 255.0f; this->setcolor(textcolor); this->updateShaderProgram(); return true;}/** * 更新Shader程序 */voID strokeLabel::updateShaderProgram() { const GLchar* fragmentSource = (GLchar*)CCString::createWithContentsOffile(CCfileUtils::sharedfileUtils()->fullPathForfilename("Label_outline1.frag").c_str())->getCString(); CCGLProgram* pProgram = new CCGLProgram(); pProgram->initWithVertexShaderByteArray(ccpositionTexturecolor_vert,fragmentSource); setShaderProgram(pProgram); pProgram->release(); CHECK_GL_ERROR_DEBUG(); getShaderProgram()->addAttribute(kCCAttributenameposition,kCCVertexAttrib_position); getShaderProgram()->addAttribute(kCCAttributenamecolor,kCCVertexAttrib_color); getShaderProgram()->addAttribute(kCCAttributenameTexCoord,kCCVertexAttrib_TexCoords); CHECK_GL_ERROR_DEBUG(); getShaderProgram()->link(); CHECK_GL_ERROR_DEBUG(); getShaderProgram()->updateUniforms(); m_uniformEffectcolor = glGetUniformlocation(getShaderProgram()->getProgram(),"u_effectcolor"); }voID strokeLabel::draw() { long long int startTime = getNowTime(); CC_PROfileR_START_category(kCCProfilercategorySprite,"CCSprite - draw"); CCAssert(!m_pobBatchNode,"If CCSprite is being rendered by CCSpriteBatchNode,CCSprite#draw SHOulD NOT be called"); CC_NODE_DRAW_SETUP(); ccGLBlendFunc( m_sBlendFunc.src,m_sBlendFunc.dst ); getShaderProgram()->use(); getShaderProgram()->setUniformlocationWith4f(m_uniformEffectcolor,m_effectcolorF.r,m_effectcolorF.g,m_effectcolorF.b,m_effectcolorF.a); getShaderProgram()->setUniformsForBuiltins(); ccGLBindTexture2D( m_pobTexture->getname() ); ccGLEnabLevertexAttribs( kCCVertexAttribFlag_PoscolorTex ); #define kQuadSize sizeof(m_squad.bl)#ifdef EMSCRIPTEN long offset = 0; setGLBufferData(&m_squad,4 * kQuadSize,0);#else long offset = (long)&m_squad;#endif // EMSCRIPTEN // vertex int diff = offsetof( ccV3F_C4B_T2F,vertices); glVertexAttribPointer(kCCVertexAttrib_position,3,GL_float,GL_FALSE,kQuadSize,(voID*) (offset + diff)); // texCoods diff = offsetof( ccV3F_C4B_T2F,texCoords); glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,(voID*)(offset + diff)); // color diff = offsetof( ccV3F_C4B_T2F,colors); glVertexAttribPointer(kCCVertexAttrib_color,4,GL_UNSIGNED_BYTE,GL_TRUE,(voID*)(offset + diff)); glDrawArrays(GL_TRIANGLE_STRIP,4); CHECK_GL_ERROR_DEBUG(); #if CC_SPRITE_DEBUG_DRAW == 1 // draw bounding Box CCPoint vertices[4]={ ccp(m_squad.tl.vertices.x,m_squad.tl.vertices.y),ccp(m_squad.bl.vertices.x,m_squad.bl.vertices.y),ccp(m_squad.br.vertices.x,m_squad.br.vertices.y),ccp(m_squad.tr.vertices.x,m_squad.tr.vertices.y),}; ccDrawpoly(vertices,true);#elif CC_SPRITE_DEBUG_DRAW == 2 // draw texture Box CCSize s = this->getTextureRect().size; CCPoint offsetPix = this->getoffsetposition(); CCPoint vertices[4] = { ccp(offsetPix.x,offsetPix.y),ccp(offsetPix.x+s.wIDth,offsetPix.y+s.height),ccp(offsetPix.x,offsetPix.y+s.height) }; ccDrawpoly(vertices,true);#endif // CC_SPRITE_DEBUG_DRAW CC_INCREMENT_GL_DRAWS(1); CC_PROfileR_Stop_category(kCCProfilercategorySprite,"CCSprite - draw"); long long int endTime = getNowTime(); long long int druation = endTime - startTime; cclOG("drawTime %lld",druation); }
我在每一次绘制都打印了一下绘制消耗的时间,单位是毫秒,基本都近似于0~1毫秒,所以绘制效率还是很高的。
用这个shader描边描出来的效果在2dx上的表现一般,描的很浅,下面是普通白字和白字描红边的对比效果图。
这是在Ios上描边效果,AndroID的效果也差不多。
描边的代码在这里下载:http://download.csdn.net/download/oktears/8403783
本文由CC原创总结,如需转载请注明出处:http://blog.csdn.net/oktears/article/details/43200757
总结以上是内存溢出为你收集整理的cocos2d-x 2.x版本文字描边研究01_使用shader描边全部内容,希望文章能够帮你解决cocos2d-x 2.x版本文字描边研究01_使用shader描边所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)