使用CEGUI+osg进行集成,照着网上的例子抄了抄,在osg3.0版本下运行没有问题,但切换到3.6 版本就怎么都无法出现界面,后来发现,是自己使用过程中,对代码的理解不够清晰,仅限于抄代码,而没有去理解为什么这样写,知其然,不知其所以然,肯定是不行的,为此付出了大量宝贵事件,特以此为警戒。
出现错误的代码为:
···C++
void CeGuiMainWindow::drawImplementation(osg::RenderInfo& renderInfo) const
{
osg::State* state = renderInfo.getState();
if (state->getContextID()!=_activeContextID) return;
glPushAttrib(GL_ALL_ATTRIB_BITS);
state->disableAllVertexArrays(); // 就是这一句话,害死人
CEGUI::System::getSingleton().renderAllGUIContexts();
glPopAttrib();
state->checkGLErrors("CEGUIDrawable::drawImplementation");
}
···
以上代码,osg3.0下没有问题,到3.6就怎么都出不来效果,后来把 state->disableAllVertexArrays();这句去掉就可以了,官方论坛也有类似问题,有人回答说在disableAllVertexArrays()后加上:
state->setClientActiveTextureUnit(0);
state->setActiveTextureUnit(0);
其实,目的就是对opengl状态的启用禁用 disableAllVertexArrays(3.0和3.6内部干的事好像一样)会禁用掉opengl绘制和顶点先关的属性,如顶点属性,纹理坐标属性等,而cegui在绘图中,没有自动开启,所以导致无法绘制.
3.0 版本,有关纹理单元代码:
inline void disableTexCoordPointersAboveAndIncluding( unsigned int unit )
{
#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE
if (_useVertexAttributeAliasing)
{
disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
}
else
{
while (unit<_texCoordArrayList.size())
{
EnabledArrayPair& eap = _texCoordArrayList[unit];
if (eap._enabled || eap._dirty)
{
if (setClientActiveTextureUnit(unit))
{
eap._lazy_disable = false;
eap._enabled = false;
eap._dirty = false;
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
++unit;
}
}
#else
disableVertexAttribPointersAboveAndIncluding(_texCoordAliasList[unit]._location);
#endif
}
默认值除了0号单元没禁用,其他都禁用了
到3.6 则内部有大改动, 跟踪内部发现,所有纹理单元全禁用了,所以需要调用disableAllVertexArrays后再启用
Textunit 0号单元。