[solved] Convert data to texture(s)

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

[solved] Convert data to texture(s)

Post by stepan1117 »

Hello everyone,
I am trying to turn unsigned char * data into the irrlicht texture (from gstreamer, but it is not important here), but I get only some messed B&W picture. The format of input data is

Code: Select all

video/x-raw-rgb,pixel-aspect-ratio=1/1,bpp=(int)24,depth=(int)24,endianness=(int)4321,red_mask=(int)0xff0000, green_mask=(int)0x00ff00, blue_mask=(int)0x0000ff
, video buffers have a stride that is rounded up to the nearest multiple of 4 and the code I am using to push it into texture is following:

Code: Select all

CurrentImage = IrrVideoDriver->createImageFromData(irr::video::ECF_A8R8G8B8,
                       irr::core::dimension2d<irr::u32>(currentW, currentH),
                       data,
                       true);
CurrentTexture = IrrVideoDriver->addTexture("movie", CurrentImage);
When I use ECF_R8G8B8, the result is different, but still garbled.
I think, that the image stride is the problem here, because when I use gdk pixbuf, then the resulting picture is fine:

Code: Select all

/* create pixmap from buffer and save, video buffers have a stride
	     * that is rounded up to the nearest multiple of 4 */
	    pixbuf = gdk_pixbuf_new_from_data (buffer,
	        GDK_COLORSPACE_RGB, FALSE, 8, width, height,
	        ROUND_UP_4 (width * 3), NULL, NULL);
So my question is, if there some fast way how to convert it into Irrlicht texture? I know, that I can use setPixel() on texture and it will be fine, but I am updating this texture 25 times per second, so that would be really a bottleneck..
Many thanks in advance,
Stepan
Last edited by stepan1117 on Tue Mar 31, 2009 3:02 pm, edited 1 time in total.
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

Re: Convert data to texture(s)

Post by stepan1117 »

Problem solved, it has nothing to do with pitch/stride (hopefully). You have to use the following caps for gstreamer

Code: Select all

"video/x-raw-rgb,pixel-aspect-ratio=1/1,bpp=(int)32,depth=(int)32,endianness=(int)4321,red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255"
use ECF_A8R8G8B8 as color format and copy each pixel in following way (maybe memcpy would be faster):

Code: Select all

p = (s32*)CurrentTexture->lock ();

for (int i = 0; i < currentW*currentH; i++) {
    	p[i] =   ((s32 *)data)[i] ;
}

CurrentTexture->unlock();
I am getting cca 2000 fps when drawing only one texture using gstreamer and irrlicht in this way.
Best regards,
Stepan
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Hint: Usage of a rendertargettexture will speed up the lock/unlock process :)
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

Post by stepan1117 »

Nox wrote:Hint: Usage of a rendertargettexture will speed up the lock/unlock process :)
Thanks, I'll use it... BTW, is it possible to resize a texture in irrlicht? I know, that there are many threads about this issue here in the forum, but I am not very clever of them and what I have understood so far is that I have to write my own resize functions to make it work... I am rendering the texture on background, using driver->draw2DImage, and I'd like to resize the texture when user resizes the window.
If it is not possible to do it using irrlicht, then I can utilize gstreamer for resize, it should not be a problem.
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

You can call an overloaded version of driver->draw2DImage which scals your image hardwareside. But you have to set a SMaterial before to clean the Renderstates and with your own SMaterial you can use a trilinear filter to improve the result afaik.
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

Post by stepan1117 »

Nox wrote:You can call an overloaded version of driver->draw2DImage which scals your image hardwareside. But you have to set a SMaterial before to clean the Renderstates and with your own SMaterial you can use a trilinear filter to improve the result afaik.
Thanks for quick answer! Unfortunately, I tried that, but with no success so far. I am still getting texture tiled with images:

Code: Select all

void drawVideoTexture()
{
	if (state == playing){
		SMaterial sm = SMaterial();
		sm.setTexture(0,CurrentTexture);
		sm.setFlag(EMF_TRILINEAR_FILTER, true);
		sm.setTextureMatrix(0,sm.getTextureMatrix(0).setTextureScale(4,4));
		IrrVideoDriver->draw2DImage(
                      sm.getTexture(0),
                      irr::core::position2d<irr::s32>(0,0), 
                      irr::core::rect<irr::s32>(0,0,currentW,currentH), 
                      &irr::core::rect<irr::s32>(0,0,desiredW,desiredH));
	}
}
I think I am missing something here, but I cannot find what :)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

draw2dimage doesn't use an SMaterial, nro can you alter its behaviour via setMaterial. You have to use a 3d quad to render your texture this way. (i.e. fake 2d)
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

Post by stepan1117 »

Uh, okay... I have to place an object to the scene (e.g. cube), set size of front side of this object to the desired texture size and then draw this texture on the cube? Maybe I understand it wrong, because I am still a total beginner to Irrlicht :), but I think I cannot go this way, because I need to have the texture (video) always on background. Right now, in first step I am drawing a picture on the screen using draw2dImage and then I draw the rest of objects (smgr->drawAll). If I draw the texture on some pseudo 3d object in the scene, then I have to take care of camera position and rotation, and change the position of the 3d object so I it will still "look like" it is fixed on back. And I do not have a clue of how to achieve that...
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

hybrid, does draw2dimage not use the current set renderstates? So a call of driver->setMaterial has no effect?

@stepan1117 you use the wrong overload. Try this one:

Code: Select all

		//! Draws a part of the texture into the rectangle.
		virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
			const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
			const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
stepan1117
Posts: 10
Joined: Sun Mar 08, 2009 12:41 pm

Post by stepan1117 »

Well, Nox, you rock... And I am totally blind and stupid :) Yes, it works like a charm with the correct function. Thank you very much, you saved me another white night :) I'll purify and beautify my code and post it somewhere, since the video player which employs gstreamer is now finished.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No, draw2DImage uses set2DRenderStates, which overrides the material properties.
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

Ahh okay thanks for the information.
Post Reply