我正在尝试使用OSG中的离线渲染来获取节点的模板索引 . 我的主要程序如下:
-
深度复制我想离线渲染的节点并获取模板索引;
-
创建一个离线渲染摄像头,并将之前复制的节点作为摄像头的子节点,然后将此摄像头作为子节点添加到我想要离线渲染的原始节点;
-
创建一个DrawCallback,它获取模板缓冲区并检查每个像素的模板索引,并获得最大的模板索引 .
好的,程序看起来有点长 . 现在我可以获得正确的最大模板索引,但是,我得到警告和错误:
“RenderStage :: runCameraSetUp(),FBO设置失败,FBO状态= 0x8cdd”“警告:在SceneView :: draw()结束时检测到OpenGL错误'无效操作'...”
整个代码有点冗长乏味 . 下面列出了一些主要代码段:
void OfflineCallback::operator()(osg::RenderInfo &renderInfo)const
{
osg::Image *image = new osg::Image;
image->readPixels(0, 0, 512, 512, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE);
unsigned char *dtBuf = (unsigned char *)(image->getDataPointer());
int maxStencil = 0;
for (int i = 0; i != image->s(); ++i){
for (int j = 0; j != image->t(); ++j){
unsigned char dt = dtBuf[image->s() * i + j];
if(dt > maxStencil)
maxStencil = dt;
}
}
}
然后我创建离线渲染摄像头,并附加模板缓冲区:
osg::Camera *camera = new osg::Camera;
camera->setClearMasks(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
camera->attach(osg::Camera::STENCIL_BUFFER, GL_UNSIGNED_BYTE);
osg::Stencil *stencil = new osg::Stencil;
stencil->setFunction(osg::Stencil::GREATER, 1, 0xff);
stencil->setOperation(osg::Stencil::INCR, osg::Stencil::INCR, osg::Stencil::INCR);
osg::Depth *depth = new osg::Depth;
depth->setFunction(osg::Depth::ALWAYS);
osg::StateSet *ss = camera->getOrCreateStateSet();
ss->setAttributeAndModes(stencil, osg::StateAttribute::ON);
ss->setAttributeAndModes(depth, osg::StateAttribute::ON);
camera->setPostDrawCallback(new OfflineCallback);
为了测试代码,我创建一个球体作为主节点,然后我得到最大的模板索引为2,这是正确的,但开头提到的错误和警告 .
我错过了什么?哪一步错了?任何建议将不胜感激 . 谢谢!
真诚的,吉米
2 回答
1
这个电话看起来很可疑:
camera->attach(osg::Camera::STENCIL_BUFFER, GL_UNSIGNED_BYTE);
我没有使用过OSG,但根据文档,这个方法的第二个参数是internalFormat,它直接对应于模板附件内部格式的OpenGL GLenum
值 . GL_UNSIGNED_BYTE
不是模板缓冲区的有效值内部格式 . 这需要 GL_STENCIL_INDEX
,或其大小的变体之一 . 例如:
camera->attach(osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX8);
除此之外, 0x8cdd
是 GL_FRAMEBUFFER_UNSUPPORTED
的值 . 这意味着(稍微从规范中解释),"the combination of internal formats of the attached images violates an implementation-dependent set of restrictions."
OpenGL实现可以为未按要求指定的任何附件组合提供此错误,如OpenGL 4.5规范中“9.4.3必需的帧缓冲区格式”一节中所述 .
如果在修复模板格式后仍然出现此错误,我强烈怀疑您的尝试失败,因为您使用单独的缓冲区进行深度和模板 . 第9.4.3节特别提到了这种情况:
但是,当存在深度和模板附件时,仅需要实现支持帧缓冲对象,其中两个附件都引用相同的图像 .
当需要深度和模板时,供应商通常仅支持组合深度/模板 . 在内部,通常存在单个32位/像素缓冲器,其具有24位深度和8位模板数据 .
所以如果你现在有这样的东西:
camera->attach(osg::Camera::DEPTH_BUFFER, GL_DEPTH_COMPONENT24);
...
camera->attach(osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX8);
如果希望代码在大多数平台上运行,则应使用组合深度/模板缓冲区:
camera->attach(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8);