CuteAlien wrote: Sun May 10, 2026 3:40 pm
You can also use the Irrlicht functions directly. Bascially - create an IImage and ITexture with same sizes and format. Work with the setPixel functions of IImage. Then as above use lock() on ITexture and lock() or getData on the IImage. Then copy the IImage data over to the texture. While that is usually slower, you don't have to write the pxiel functions yourself. But... slow - those are even virtual function calls. Good enough for simple stuff, but if you do more in your application this can start being too expensive.
All right, so I had to google a lot of stuff, because this is more low-level than I'm used to, but in the end, I've managed to write the PutTexel function the way I wanted to.
Code: Select all
void dlPutTexel(ITexture* texture, uint16_t x, uint16_t y, uint8_t red, uint8_t green, uint8_t blue)
{
// This function puts a single pixel on a texture
uint16_t image_x, image_y; // 65535*65535 pixels ought to be enough for everyone
IImage* bak;
// Note to self: a void pointer can hold an address of any type and can be typecasted to any type
void* imagedata;
void* texturedata;
u32 datasize;
image_x=texture->getSize().Width;
image_y=texture->getSize().Height;
bak=driver->createImage(video::ECF_A8R8G8B8, core::dimension2d<u32>(image_x,image_y));
// texture data is copied to the backup (necessary, otherwise anu graphical operation will erase the previous ones)
// lock the IImage to get access to the raw pixel array
imagedata=bak->lock();
// lock the texture to get access to GPU memory
texturedata=texture->lock();
if (texturedata&&imagedata)
{
// data size in bytes is the IImage size in pixels, multiplied by 4 because each pixel holds 4 bytes of data
// (alpha, red, green, blue)
datasize=bak->getDimension().Width*bak->getDimension().Height*4;
// perform the copy (this is when the texture modification appears)
memcpy(imagedata,texturedata,datasize);
// unlock both because the pointers aren't needed anymore
texture->unlock();
bak->unlock();
}
// all pixel operations must be done here
bak->setPixel(x,y,SColor(255,red,green,blue),false);
// lock the IImage to get access to the raw pixel array
imagedata=bak->lock();
// lock the texture to get access to GPU memory
texturedata=texture->lock();
if (texturedata&&imagedata)
{
// data size in bytes is the IImage size in pixels, multiplied by 4 because each pixel holds 4 bytes of data
// (alpha, red, green, blue)
datasize=bak->getDimension().Width*bak->getDimension().Height*4;
// perform the copy (this is when the texture modification appears)
memcpy(texturedata,imagedata,datasize);
// unlock both because the pointers aren't needed anymore
texture->unlock();
bak->unlock();
}
}
I was about to ask about void pointers, because the page I copypasted that part of the code from didn't explain them and I got them confused with null pointers, but then I googled "void pointer" and learned what they are.
All I have to do now is to time the function to see whether it's fast enough for what I need.