Page 1 of 1

rtt

Posted: Wed Jan 27, 2010 8:14 am
by pin3
could some one post code on how to lock/write to individual pixels when doing render to texture

Posted: Wed Jan 27, 2010 8:24 am
by hybrid
If you just want to write a very few pixels, you can use drawPixel. Otherwise simply lock() the texture and cast the returned pointer to e.g. u8*. then you can write each byte of the texture. Depending on the color format, each pixel has 2-4 bytes. The elements of each pixel are given in the color format. Once you unlock the texture it is uploaded to the GPU.

Posted: Wed Jan 27, 2010 8:39 am
by pin3
thx hybrid

code I came up with off the bat



u8 * Pixel = 0;

while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, 0);

if (rt)
{
// draw scene into render target

// set render target texture
// 128x128 texture
driver->setRenderTarget(rt, true, true, video::SColor(0,0,0,255));

Pixel = rt->Lock();

for(int z = 0; z< 128; z++)
{
for(int x = 0; x< 128; x++)
{
Pixel[z * 128 + x] = a * r * g * b;
}
}

// a, r, g, b ints ranging from 0 to 256

Posted: Wed Jan 27, 2010 11:29 am
by hybrid
You should lock the rtt outside the beginScene/endScene, just to be sure that the rtt is not in use. Moreover, the color value needs to be different. If you have an A8R8G8B8 texture you can write SColor.color to the pixel, otherwise use a conversion method from SColor.h to convert to the 16bit values.

Posted: Tue Mar 09, 2010 7:48 am
by pin3
bumping this

in irrlicht 1.7 locking a texture returns void pointer not u8 how do I write pixel to the texture

Posted: Tue Mar 09, 2010 8:44 am
by Brainsaw
maybe you could cast the void pointer?

Posted: Tue Mar 09, 2010 8:58 am
by hybrid
lock has always returned a void* simply because it's not necessarily a u8*, but could also be a u32* or u16*

Posted: Tue Mar 09, 2010 9:37 am
by Nalin
Here is an example. It comes from my CGUITTFont class. In this code fragment, I am converting a FreeType font bitmap into an Irrlicht IImage. FreeType stores the font as an alpha channel. That is, each "pixel" is actually just an 8-bit alpha value.

IImage and ITexture both have a lock() function for grabbing the raw pixel data, so you can learn from this example.

Code: Select all

// Create our blank image.
// texture_size is a dimension2du that is storing the size of our texture.
image = driver->createImage(video::ECF_A8R8G8B8, texture_size);

// Fill the image with black pixels with an alpha of 0.
// FreeType returns just an alpha channel, so we will overwrite the alpha values
// in the code below.
image->fill(video::SColor(0, 255, 255, 255));

// In Irrlicht, pitch is the number of bits for 1 row of pixels.
// We divide by u32 to return how many pixels are in one row.
// Sometimes, an image may have some unused border pixels, so the width will not
// be the same as the pitch, so always use pitch when calculating our
// location manually!
const u32 image_pitch = image->getPitch() / sizeof(u32);

// Here is where we lock the texture.  Our image is A8R8G8B8,
// so one full pixel is 32-bits.
// The first 8 are alpha, next 8 are red, then green, and the last 8 are blue.
// I cast the pointer to u32 so when I increment the pointer,
// I move forward one full pixel.
u32* data = (u32*)image->lock();

// This is a pointer to the FreeType bitmap.
u8* row = glyph->bitmap.buffer;

// Now, I iterate through the FreeType bitmap.
for (s32 y = 0; y < bits.rows; ++y)
{
    // I create a new pointer to point to the current row in the FreeType bitmap.
    u8* bitsdata = row;

    // Now, I iterate through each pixel in the FreeType bitmap row.
    // y * image_pitch + x will return the current pixel in our
    // image to manipulate.
    // *bitsdata++ will return the current alpha value I am looking at
    // in the FreeType bitmap,
    // then increment to the next value.
    // Since *bitsdata is returning an alpha value, we shift it 24 bits to the left.
    // That places at the location of alpha in a 32-bit A8R8G8B8 pixel.
    for (s32 x = 0; x < bits.width; ++x)
        data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24);

    // We want to go to the next row now,
    // so we increment our row pointer by the pitch.
    row += bits.pitch;
}
image->unlock();

Posted: Wed Mar 10, 2010 6:08 am
by pin3
Ok so I got

u32* data = (u32*)image->lock();

the question is what do I use u32, u16 or u8? Is it dependant on the image format?


ISceneNode* n = M->addCubeSceneNode(60);
ITexture* t = 0;



if (R->queryFeature(video::EVDF_RENDER_TO_TARGET))
{
t = R->addRenderTargetTexture(core::dimension2d<u32>(256,256), "RTT1");
n->setMaterialTexture(0, t);
}

u32* P = (u32*)t->lock();

Posted: Wed Mar 10, 2010 8:35 am
by hybrid
Of course you could always use u8*, as that's the smallest unit. However, it complicates the color interpretations. The actual pixel elements depend on the color values, usually using u16 or u32, and 3*u8 for RGB8.

Posted: Wed Mar 10, 2010 10:01 am
by arras
the question is what do I use u32, u16 or u8? Is it dependant on the image format?
Yes.

ECF_A8R8G8B8 equals to u32 as its 32 bit format
ECF_A1R5G5B5 equals to u16 as it is 16 bit format.

Look at the documentation of irr::video::ECOLOR_FORMAT or in to SColor.h source.