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
by 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
=====================================================================
比较简单的解决办法是在创建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用于绘制,暂时还没深入研究。