2016-08-28 5 views
1

Я пытаюсь получить индекс трафарета узла, используя автономный рендеринг в OSG. Мои основные процедуры перечислены ниже:Ошибки FBO при получении буфера трафарета с использованием OSG

  1. глубоко скопируйте узел, который я хочу выполнить в автономном режиме, и получаю индекс трафарета;
  2. Создайте автономную камеру рендеринга и сделайте предыдущий скопированный узел дочерним элементом камеры, а затем добавьте эту камеру в качестве дочернего узла в исходный узел, который я хочу выполнить в автономном режиме;
  3. создать DrawCallback, который получает буфер трафарета и проверяет индексы трафарета каждого пикселя и получает максимальный индекс трафарета.

Хорошо, процедуры выглядят немного длинными. Теперь я могу получить правильный индекс максимального трафарета, однако, я получаю предупреждение и ошибки:

«RenderStage :: runCameraSetUp(), настройка FBO неудачные, статус FBO = 0x8cdd» «Предупреждение: обнаружена ошибка OpenGL» недопустимая операция 'в конце SceneView :: draw() ... "

Все коды немного длинны и утомительны. Некоторые основные фрагменты кода перечислены ниже:

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, который является правильным, но с ошибками и предупреждениями, упомянутыми в начале.

Что мне не хватает? Какой шаг неправильный? Любое предложение будет оценено по достоинству. Благодаря!

С уважением, Джимми

ответ

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. Это означает, что (слегка перефразированный из спецификации), «комбинация внутренних форматов прикрепленных изображений нарушает набор ограничений, зависящих от реализации».

Реализации OpenGL могут давать эту ошибку для любой комбинации вложений, которая не указана по мере необходимости, как описано в разделе «9.4.3. Необходимые форматы фреймбуфферов» в спецификации OpenGL 4.5.

Если вы все еще получаете эту ошибку после исправления формата трафарета, я сильно подозреваю, что ваша попытка не удалась, потому что вы используете отдельные буферы для глубины и трафарета. Этот случай конкретно упоминается в разделе 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); 
+0

Спасибо, Reto! Ваши предложения действительно полезны. Когда я устанавливаю приложение камеры как: camera-> attach (osg :: Camera :: PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8); FBO кажется успешно создан. Тем не менее, я до сих пор не знаю, как читать его с помощью readPixels. Не могли бы вы дать какие-либо предложения по этому поводу? –

1

ОК, наконец, Я получаю правильный индекс трафарета и, что более важно, без каких-либо ошибок и предупреждений!

Ответ Reto по-прежнему весьма полезен. Еще раз спасибо, Reto! Его основной задачей является то, что вы хотите получить одновременно глубинные буферы трафаретов глубины , большинство поставщиков предоставят вам только буфер глубины трафарета.

Таким образом, если вы подключите глубину & буфера трафарета к FBO независимо в одно и то же время, вы в значительной степени не сможете создать FBO. Именно по этой причине я получаю ошибки и предупреждения в первую очередь.

Подробные причины: камера OSG неявно создает цветные буферы глубины &, но не создает буфер трафарета. Это нормально для большинства случаев. Однако в моем случае я явно хочу использовать буфер трафарета. Поэтому, наконец, камера OSG создает для меня все три буфера. Поскольку, как упоминалось ранее, независимая глубина буферов трафарета & приведет к сбою в создании FBO, поэтому я получаю все предупреждения и ошибки.

Решение:

image->allocateImage(512, 512, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE); 
camera->attach(osg::Camera::STENCIL_BUFFER, image); 
//explicitly tells camera not to implicitly create color & depth buffers 
camera->setImplicitBufferAttachmentRenderMask(0); 

И в DrawCallback, вы можете прочитать индексы трафарет легко, так же, как глубина чтения буфера.

Если у кого-то есть другие идеи или исправления, я все уши!

 Смежные вопросы

  • Нет связанных вопросов^_^