0
\$\begingroup\$

I'm using Ogre 1.10, I have a dynamic texture assigned to a material that I need to update its buffer with a new image every few seconds. How can I transfer pixel data from an image to my dynamic texture?

I've created a manual texture like:

         // Create the texture
        Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual(
            "dyn_texture", // name
            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            Ogre::TEX_TYPE_2D,      // type
            256, 256,         // width & height
            0,                // number of mipmaps
            Ogre::PF_BYTE_BGRA,     // pixel format
            Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);

And on my update function I have the image that I want to transfer:

Ogre::Image img;
img.load(basename.toStdString(), "resources");
//Copy pixels from img to texture
//??

I've already tried doing:

Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();
pixelBuffer->blitFromMemory(img.getPixelBox());

works but it's quite slow, gui freezes when updating like that.

\$\endgroup\$
0
\$\begingroup\$

Answering my own question, I did the following:

//Using Qt to load an image, Ogre::Image can be used as well
QImage qimg = QImage("someTexture.jpg");

//Get texture ptr
Ogre::TexturePtr texture = Ogre::TextureManager::getSingletonPtr()->getByName("myTexture");
Ogre::HardwarePixelBufferSharedPtr buffer = texture->getBuffer();
/// Lock the buffer so we can write to it
buffer->lock(_box, Ogre::HardwareBuffer::HBL_DISCARD); //Fast!!
const Ogre::PixelBox &pb = buffer->getCurrentLock();

/// Update the contents of pb here
/// Image data starts at pb.data and has format pb.format
/// Here we assume data.format is PF_X8R8G8B8 so we can address pixels as uint32.
uint32_T *data = static_cast<uint32_T*>(pb.data);
const uint32_T *data_img = reinterpret_cast<const uint32_T*>(qimg.constBits());
int height = qimg.height();
int width = qimg.width();;
size_t pitch = pb.rowPitch;
for(int y=0; y<height; ++y)
{
    for(int x=0; x<width; ++x)
    {
        data[pitch*y + x] = data_img[pitch*y + x];
    }
}

/// Unlock the buffer again (frees it for use by the GPU)
buffer->unlock();

I did a short benchmark and this technique is faster than using HardwarePixelBufferSharedPtr::blitFromMemory() (jpeg, 256x256px)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.