Ogre 3d: RenderTexture больше, чем RenderWindow

#c #linux #opengl #ogre3d

#c #linux #opengl #ogre3d

Вопрос:

У меня есть два приложения ogre:

1) Дополнительное приложение, которое отображает окно и текстуру (используя ту же камеру). Текстура «экспортируется» в общую память (shm в Linux)

2) Основное приложение, где плоскость показывает, что происходит в (1) «вспомогательном приложении», загружающем текстуру из общей памяти.

Текстура, в которой (1) отображается, имеет тот же размер, что и текстура, используемая плоскостью в (2). Например: 512×512

Все работает нормально, если RenderWindow больше или равно RenderTexture. То, что вы видите в (1), отражается в (2) плоскости с приличным fps. Разделяемая память — это мощно!

Но если окно рендеринга меньше текстуры, обновляется только часть текстуры.

Это то, что происходит со мной: renderwindow меньше, чем rendertexture

В некоторых примерах показано окно размером 1×1 и большая текстура рендеринга, поэтому я предполагаю, что текстура рендеринга может быть больше, чем окно.

Так создается окно:

 window_ = root_->createRenderWindow("blablah"), 256, 256, false);
 

Так создается текстура рендеринга:

 TextureManager* tm = TextureManager::getSingletonPtr();
TexturePtr rttTexture = tm->createManual(
/**/"MainRTT"
/**/, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
/**/, TEX_TYPE_2D
/**/, 512
/**/, 512
/**/, 0
/**/, PF_R8G8B8A8
/**/, TU_RENDERTARGET);
RenderTexture* renderTarget = rttTexture->getBuffer()->getRenderTarget();
renderTarget->addViewport(camera_);
renderTarget->setAutoUpdated(false);
Viewport* vp = renderTarget->getViewport(0);
vp->setClearEveryFrame(true);
vp->setOverlaysEnabled(true);
vp->setBackgroundColour(ColourValue::Black);
 

Вот как я обновляю текстуру рендеринга:

 class ShmTexUpdater: public Ogre::FrameListener {
public:
    ShmTexUpdater(const intamp; width, const intamp; height, void* data,
            const TexturePtramp; tex) :
        /**/width_(width)
        /**/, height_(height)
        /**/, data_(data)
        /**/, tex_(tex)
        /**/, buf_(tex->getBuffer())
        /**/, renderTarget_(tex->getBuffer()->getRenderTarget()){

    }
    virtual ~ShmTexUpdater() {

    }
private:
    virtual bool frameStarted(const FrameEventamp; evt) {
        FrameWork::instance()->window()->update();
        buf_->lock(Ogre::HardwareBuffer::HBL_NORMAL);
        renderTarget_->update();
        tex_->getBuffer()->blitToMemory(
        /**/PixelBox(width_, height_, 1, ShmTexture4k::FORMAT, data_));
        buf_->unlock();
        return true;
    }
    int const width_;
    int const height_;
    void* const data_;
    TexturePtr const tex_;
    HardwarePixelBufferSharedPtr buf_;
    RenderTexture* renderTarget_;
};
 

Читая описание RenderWindow и RenderTexture, это не то, чего я ожидаю. Итак … это ошибка ogre или opengl? Или я делаю это неправильно?

  • ОС: Linux
  • Ogre: версия 1.7.3 (Cthugha)
  • GL_VERSION = 4.0.0 NVIDIA 256.53

Комментарии:

1. Используется ли ваша переменная camera_ совместно с целью рендеринга Windows?

2. @crazyjul попробовал с новой камерой, скопировал с другой с помощью newCamera-> synchroniseBaseSettingsWith(camera_); но результат тот же

Ответ №1:

Я не уверен, что это сильно помогло (и, вероятно, слишком поздно), но некоторое время назад я прочитал, что OpenGL не может отображать текстуру, которая больше, чем окно, которое она использует. DX способен это сделать, но не OGL.

Кстати, извините, что это ответ, а не комментарий, но я пока не могу писать комментарии;]

Ответ №2:

Если размер цели изменится, вашу камеру необходимо обновить: http://www.ogre3d.org/docs/api/html/classOgre_1_1Viewport.html#a23c2b69bbc3d76fd52a4729a71caed08

Вызов _updateDimensions() должен исправить это

Комментарии:

1. Как говорится в документации, _updateDimensions() это » Только для внутреннего использования Ogre».. Я пытался вызвать его после vp->setBackgroundColour(ColourValue::Black); и до renderTarget_->update(); , но ничего не изменилось.

2. Цель не изменяет свой размер. Есть две разные цели: RenderWindow и RenderTexture, и оба они не меняют свой размер. Мой пример показывает, что произойдет, если RenderWindow больше, чем RenderTexture, и наоборот.

Ответ №3:

Но если окно рендеринга меньше текстуры, обновляется только часть текстуры.

Именно этого и следовало ожидать, и действительно правильное поведение. Пиксели обычных экранных окон обрабатываются только в том случае, если они проходят так называемый тест на владение пикселями. Это означает, что только те пиксели, которые будут видны пользователю, будут отображаться вообще. Так что, если, например, вы перетащите окно перед своим окном OpenGL, эти пиксели также не будут отображаться; в современных системах используется так называемое управление окнами компоновки, где препятствие окном не подведет тест на владение пикселями.

Короче говоря: если вы рендерите материал для последующей обработки, вы должны делать это в фреймбуфере, полностью находящемся под вашим контролем: PBuffer или объект Frame Buffer.

Комментарии:

1. Я провел несколько тестов после вашего ответа… При включенном или отключенном composite он все равно продолжает обновляться, даже если окно рендеринга не видно (закрыто другим окном, уменьшено до значка или находится на другом виртуальном рабочем столе). Это произойдет, если я принудительно обновлю с renderTarget_->update(); помощью . Так что, я думаю, это не проблема. Верно?

2. @AlessandroPezzato: Какую ОС и композитор вы используете? В любом случае, вы не должны использовать Windows в качестве цели рендеринга для содержимого рендеринга в текстуру. Используйте FBO или PBuffer, вот для чего они предназначены.

3. Это kde 4.6 с его композитором. Мое приложение Ogre визуализирует окно и текстуру ( ogre3d.org/tikiwiki/Intermediate Учебное пособие 7 ).