`
yuanjinxiu
  • 浏览: 660056 次
文章分类
社区版块
存档分类
最新评论

第二人生的源码分析(二十一)显示人物名称的字体

 
阅读更多
前面已经介绍了显示人物名称的基本框架,但是使用OpenGL显示这个名称出来是需要很复杂的步骤。由于OpenGL是图形引擎显示,也就是说所有字符的显示都是基于图形来显示,而图形的显示,就需要获取字体的图片,即是获取字体的字模。由于不能使用Windows的标准GDI来显示,那么就需要实现GDI所做的所有功能,比如从字体里读取每个字符的轮廓,然后生成合适大小的位图,再把这幅位图当作纹理贴到3D的平面上去,这样才可以在OpenGL显示字符串出来。在第二人生里的代码流程如下:
1、LLFontGL::addChar() 添加一个字符纹理图片
2、mImageGLp->bind() 绑定纹理图片。
3、LLImageGL::bindTextureInternal() 真正绑定纹理图片,在这个函数里调用glBindTexture函数来绑定纹理。
4、LLFontGL::render() 这个函数显示所有字符串。
仔细地分析一下这个函数,看看怎么样显示字符串的,如下:
#001S32 LLFontGL::render(const LLWString &wstr,
#002 const S32 begin_offset,
#003 const F32 x, const F32 y,
#004 const LLColor4 &color,
#005 const HAlign halign, const VAlign valign,
#006 U8 style,
#007 const S32 max_chars, S32 max_pixels,
#008 F32* right_x,
#009 BOOL use_embedded,
#010 BOOL use_ellipses) const
#011{
#012 LLGLEnable texture_2d(GL_TEXTURE_2D);
#013
下面绑定纹理图片。
#089
#090 // Bind the font texture
#091
#092 mImageGLp->bind(0);
#093
#094 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Not guaranteed to be set correctly
#095
下面开始循环地显示字符串。
#160
#161 for (i = begin_offset; i < begin_offset + length; i++)
#162 {
#163 llwchar wch = wstr[i];
#164
#165 // Handle embedded characters first, if they're enabled.
#166 // Embedded characters are a hack for notecards
#167 const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL;
#168 if (ext_data)
#169 {
……
#224 // Bind the font texture
#225 mImageGLp->bind();
#226 }
#227 else
#228 {
#229 if (!hasGlyph(wch))
#230 {
#231 (const_cast<LLFontGL*>(this))->addChar(wch);
#232 }
#233
#234 const LLFontGlyphInfo* fgi= getGlyphInfo(wch);
#235 if (!fgi)
#236 {
#237 llerrs << "Missing Glyph Info" << llendl;
#238 break;
#239 }
#240 if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
#241 {
#242 // Not enough room for this character.
#243 break;
#244 }
#245
#246 // Draw the text at the appropriate location
#247 //Specify vertices and texture coordinates
#248 LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
#249 (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height,
#250 (fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
#251 (fgi->mYBitmapOffset - PAD_AMT) * inv_height);
#252 LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT,
#253 cur_render_y + (F32)fgi->mYBearing + PAD_AMT,
#254 cur_render_x + (F32)fgi->mXBearing + (F32)fgi-
#255>mWidth + PAD_AMT,
#256 cur_render_y + (F32)fgi->mYBearing - (F32)fgi-
#257>mHeight - PAD_AMT);
#258
这里设置每个字符的纹理坐标以及顶点坐标。
#259 drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
#260
#261 chars_drawn++;
#262 cur_x += fgi->mXAdvance;
#263 cur_y += fgi->mYAdvance;
#264
#265 llwchar next_char = wstr[i+1];
#266 if (next_char && (next_char < LAST_CHARACTER))
#267 {
#268 // Kern this puppy.
#269 if (!hasGlyph(next_char))
#270 {
#271 (const_cast<LLFontGL*>(this))->addChar(next_char);
#272 }
#273 cur_x += getXKerning(wch, next_char);
#274 }
#275
#276 // Round after kerning.
#277 // Must do this to cur_x, not just to cur_render_x, otherwise you
#278 // will squish sub-pixel kerned characters too close together.
#279 // For example, "CCCCC" looks bad.
#280 cur_x = (F32)llfloor(cur_x + 0.5f);
#281 //cur_y = (F32)llfloor(cur_y + 0.5f);
#282
#283 cur_render_x = cur_x;
#284 cur_render_y = cur_y;
#285 }
#286 }
#287
……
#320 glPopMatrix();
#321 }
#322
#323 glPopMatrix();
#324
#325 return chars_drawn;
#326}
#327

蔡军生 <chsdate w:st="on" isrocdate="False" islunardate="False" day="24" month="1" year="2008">2008/01/25</chsdate> QQ:9073204 深圳

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics