fix Ogre 1.7.2 text overlay not showing up bug(Ogre文字不显示bug)(转载)

原文在:http://blog.sina.com.cn/s/blog_7a6871250100s0t2.html

弄了半天overlay不显示字,到处搜索原来还是ogre的bug。

===================

Ogre 1.7.2 text rendering有个bug,在Simple Text Output 这个例子里,
如果不resize窗口大小,文字是不会显示的。
bug别人查下来是没有load font的关系。
http://www.ogre3d.org/forums/viewtopic.php?f=2&t=58047
================================================================
下面是一些帖子摘要:

Re: Problem displaying text in overlay

Postby Stickymango » Fri Sep 10, 2010 10:56 am

I've traced the bug:
previously in TextAreaOverlayElement:

Code: Select all
 void TextAreaOverlayElement::setFontName( const String& font )     
{         
mpFont = FontManager::getSingleton().getByName( font );   
      if (mpFont.isNull())             
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, "Could not find font " + font,                 "TextAreaOverlayElement::setFontName" );         
mpFont->load();         
mpMaterial = mpFont->getMaterial();         
mpMaterial->setDepthCheckEnabled(false);         
mpMaterial->setLightingEnabled(false);         
mGeomPositionsOutOfDate = true;         
mGeomUVsOutOfDate = true;     
}

But now the font load code has been moved to getMaterial():
Code: Select all
   const MaterialPtr& TextAreaOverlayElement::getMaterial(void) const     { 
        // On-demand load         
// Moved from setFontName to avoid issues with background parsing of scripts
         if (mpMaterial.isNull() && !mpFont.isNull())
         {             
  mpFont->load();             // Ugly hack, but we need to override for lazy-load             *const_cast<MaterialPtr*>(&mpMaterial) = mpFont->getMaterial();             mpMaterial->setDepthCheckEnabled(false);            
 mpMaterial->setLightingEnabled(false); 
        }         
return mpMaterial;
     }

This causes the font not to be rendered the first time its used. Reverting back to the original code fixes the issue but I gather that causes issues with parsing, I haven't worked out where is the best place to insert this code yet, so I thought I'd throw it open to one of the devs who have a better understanding how the system works :wink:

=====================================================================
比较简单的解决办法是在创建overlay element之前先读取一下字体
这样就不用修改Ogre源代码了
void TextRenderer::addTextBox(const std::string& ID,
const std::string& text,
Ogre::Real x, Ogre::Real y,
Ogre::Real width, Ogre::Real height,
const Ogre::ColourValue& color)
{
// Solution:
// Load font before creating OverlayElement
Ogre::FontManager *pFontManager = Ogre::FontManager::getSingletonPtr();
Ogre::ResourceManager::ResourceCreateOrRetrieveResult res = pFontManager->createOrRetrieve("arial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
res.first->load();

Ogre::OverlayElement* textBox = _overlayMgr->createOverlayElement("TextArea", ID);
textBox->setDimensions(width, height);
textBox->setMetricsMode(Ogre::GMM_PIXELS);
textBox->setPosition(x, y);
textBox->setWidth(width);
textBox->setHeight(height);
textBox->setParameter("font_name", "arial");
textBox->setParameter("char_height", "16");
textBox->setColour(color);
textBox->setCaption(text);
_panel->addChild(textBox);
}
//=============================================
后记:这个方法其实隐含了这么一个条件:textBox会用font的material。
所以一但更改了font的material,所有的textBox的material都会相应改变。
比如把font的material改成了别的颜色,或者用了其他的shading,所有用这个font的textBox都变了。
如果想把textBox的字体和渲染方法分离,那就需要附给textBox新的material,并把其中的一层texture换成font的字体texture。
并且在font reload的时候再次设定textBox material的texture。
(font添加新code point的时候会绘制新的字体texture,但textBox的material不知道这件事情,所以要重新设定)
(resource reload有callback可以设制,可以想想怎么弄,这里不展开了)
这样一来不同的textbox就可以用不同的效果渲染了,比如字体阴影之类的效果(用shader绘制2次,平移texture坐标)。
但是要实现更复杂的效果,比如字体泛光,构边之类的还是不是很方便。
需要重写或者改写overlay textBox,构造新的vertex buffer用于绘制,暂时还没深入研究。

posted on 2012-02-17 20:43  kenshou  阅读(440)  评论(0编辑  收藏  举报