1
\$\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\$

1 Answer 1

1
\$\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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .