现在的位置: 首页 > 综合 > 正文

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

2013年10月01日 ⁄ 综合 ⁄ 共 4718字 ⁄ 字号 评论关闭
前面已经介绍了显示人物名称的基本框架,但是使用OpenGL显示这个名称出来是需要很复杂的步骤。由于OpenGL是图形引擎显示,也就是说所有字符的显示都是基于图形来显示,而图形的显示,就需要获取字体的图片,即是获取字体的字模。由于不能使用Windows的标准GDI来显示,那么就需要实现GDI所做的所有功能,比如从字体里读取每个字符的轮廓,然后生成合适大小的位图,再把这幅位图当作纹理贴到3D的平面上去,这样才可以在OpenGL显示字符串出来。在第二人生里的代码流程如下:
1、LLFontGL::addChar()    添加一个字符纹理图片
2、mImageGLp->bind()       绑定纹理图片。
3、LLImageGL::bindTextureInternal()      真正绑定纹理图片,在这个函数里调用glBindTexture函数来绑定纹理。
4、LLFontGL::render()            这个函数显示所有字符串。
仔细地分析一下这个函数,看看怎么样显示字符串的,如下:
#001 S32 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 

 

蔡军生  2008/01/25 QQ:9073204 深圳

抱歉!评论已关闭.