Hello,
Here is my first post about WPF and Mogre, maybe it will helps some people...
The subject of today is "How to use a screenshot of a WPF elements and put it as an texture on your Mogre object"...
Why ? Because WPF enable you to create very rich interface and so great image to place on you differents elements...
By the way, I let you follow the link at the end of the post to learn how to blend Mogre in WPF and how to take a screenShot of a WPF visual.
The steps to follow are these :
- Create a screenshot of the WPF visual (any visual can be used),
- Put the bitmap in a stream and then to a buffer,
- Use some unsafe code to create a Mogre MemoryStream and a mogre image,
- Use this image to create a texture,
- Use this texture in a material,
- Put it on the mesh of your choice
Create a screenshot of the WPF visual
The original code is from thomas lebrun and can be found in any good WPF book :
Visual theVisual = this ; //Put the aimed visual here.
double width = Convert.ToDouble(theVisual.GetValue(FrameworkElement.WidthProperty));
double height = Convert.ToDouble(theVisual.GetValue(FrameworkElement.HeightProperty));
if (double.IsNaN(width) || double.IsNaN(height))
{
throw new FormatException("You need to indicate the Width and Height values of the UIElement.");
}
RenderTargetBitmap render = new RenderTargetBitmap(
Convert.ToInt32(width),
Convert.ToInt32(this.GetValue(FrameworkElement.HeightProperty)),
96,
96,
PixelFormats.Pbgra32);
// Indicate which control to render in the image
render.Render(this);
Stream oStream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(render));
encoder.Save(oStream);
oStream.Flush();
Put the bitmap in a stream and then to a buffer
//Back to the start of the stream
oStream.Position = 0;
//read all the stream
BinaryReader oBinaryReader = new BinaryReader(oStream);
byte[] pBuffer = oBinaryReader.ReadBytes((int)oBinaryReader.BaseStream.Length);
oStream.Close(); //No more needed
TextureManager.Singleton.Remove(sName); //Remove eventually texture with the same name
Create the texture
unsafe
{
GCHandle handle = GCHandle.Alloc(pBuffer, GCHandleType.Pinned);
byte* pUnsafeByte = (byte*)handle.AddrOfPinnedObject();
void* pUnsafeBuffer = (void*)handle.AddrOfPinnedObject();
MemoryDataStream oMemoryStream = new MemoryDataStream(pUnsafeBuffer, (uint)pBuffer.Length);
DataStreamPtr oPtrDataStream = new DataStreamPtr(oMemoryStream);
oMogreImage = oMogreImage.Load(oPtrDataStream, "png");
TextureManager.Singleton.LoadImageW(sName, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME, oMogreImage);
//handle.Free();
}
Use this texture in a material
Here is the code of how you can create a material with this texture:
_dynamicMaterial = MaterialManager.Singleton.Create(SCREENSHOT_MATERIAL_NAME, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
Pass pass = _dynamicMaterial.GetTechnique(0).GetPass(0);
TextureUnitState tus = pass.CreateTextureUnitState(SCREENSHOT_TEXTURE_NAME);
_dynamicMaterial.GetTechnique(0).GetPass(0).AddTextureUnitState(tus);
Then you just have to use it as a normal texture...
An example:
Here is a little screenshot of the results. I display a cube with the face using as a texture a screenshot of the window in which it is....
Link: how to blend Mogre in WPF
CodeProject