Rendering to Bitmap from DLL

Started by
6 comments, last by shaKu_shawn 16 years, 6 months ago
Ok here is what I am trying to do. I have a class library that I am working on which uses references to the DirectX 9.0 DLLs. What I want to be able to do is create a function in my Class Library that I can reference from any of my windows forms projects and have it render a scene and return a BMP. I am stuck at a few spots... I have found you can use a Surface to render to a Bitmap which is exactly what I want to do. The first problem I am having is setting the device up to render without a windows form object. If anyone has an example of something like this that would be great... or any pointers to get me headed in the correct direction! Thanks in advance
Advertisement
What language are you using?

You may be able to set up your present parameters with a handle to a window that isn't visible. So long as you don't Present() your backbuffer, it won't matter. After rendering your scene (After EndScene()) you should be able to do what you like to the backbuffer, inclusing locking it, or using UpdateSurface() and so on. As far as I know (I don't recall offhand), you can't use GetDC on a surface in the default pool, so you can't use it on the backbuffer. You can however copy the backbuffer to a temp surface, then use GetDC() on that, and blit that to a HBITMAP or equivalent for your language.
Might want to look at off screen rendering...then just save it rather than use it as a texture. Have a look at:
http://www.codesampler.com/dx9src/dx9src_7.htm#dx9_offscreen_rendering
I am working in C#... here is what I have so far

public void InitializeDevice(System.Windows.Forms.Form parentForm)
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;

device = new Device(0, DeviceType.Hardware, parentForm, CreateFlags.SoftwareVertexProcessing, presentParams);
}

public Bitmap Render()
{
Bitmap surfaceBuffer = new Bitmap(256, 256, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Surface renderSurface = new Surface(device, surfaceBuffer, Pool.Default);

device.SetRenderTarget(0, renderSurface);
device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);
device.Present();

return surfaceBuffer;
}

I get an error on the device.SetRenderTarget line...
What error do you get? Have you marked the surface as being a render target (D3DUSAGE_RENDERTARGET in C++, I don't know the C# version).
hmm the i am having trouble getting this to work still... here is my current code... i can render the scene into a texture... now i need to get that texture into a BMP is this possible?

public void InitializeDevice(System.Windows.Forms.Form parentForm)
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;

device = new Device(0, DeviceType.Hardware, parentForm, CreateFlags.SoftwareVertexProcessing, presentParams);
}

public Bitmap Render()
{
Texture renderTexture = new Texture(device, 256, 256, 0, Usage.RenderTarget, Format.X8R8G8B8, Pool.Default);
//Texture renderTexture = new Texture(device, 256, 256, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Managed);


device.SetRenderTarget(0, renderTexture.GetSurfaceLevel(0));
device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);
device.Present();


//return bitmap;
return surfaceBuffer;
}
Can you not specify usage with a surface?

You could always use UpdateSurface() or whatever the C# equivalent is to copy the render target surface contents to a system memory surface, and then use GetDC (Again, or the C# equivalent) on that surface to BitBlt to a Bitmap.

This may or may not be revelent, C# surfaces seem to be a bit different from the C++ versions; you can't specify a "Bitmap" to use with a surface in C++...

Also, what do you want to do with this bitmap once you have it? Is it a GDI bitmap handle? Or do you want to save it?
Ok I have it figured out... I use a texture like so...

Texture renderTexture = new Texture(device, 256, 256, 0, Usage.RenderTarget, Format.X8R8G8B8, Pool.Default);

and set the device RenderTarget to renderTexture.GetSurfaceLevel(0) and it works fine to render to the texture.

Now I have 2 new problems... the first being when I want to save out that texture I do the following..

SurfaceLoader.Save("textures/trenders/rendered/" + uniqueName, ImageFileFormat.Png, renderTexture.GetSurfaceLevel(0));

and it works fine... then the current way i do it is reload that saved BMP file... the ideal way would be to use the SaveToStream method but I cant get it to work... here is the code i have so far...

GraphicsStream stream = SurfaceLoader.SaveToStream(ImageFileFormat.Bmp, renderTexture.GetSurfaceLevel(0));
Bitmap bmp = new Bitmap(256, 256, 256*4, PixelFormat.Format32bppArgb, stream.InternalData);

when i use this stream method i get back a strange looking image.. its the image I am expecting just very gray and has pink in it which leads me to beleive I am either not using the correct pixelformat or read size...



My last problem comes before this when i am loading my texture to draw in the scene... when i use the following method

Texture testTexture = TextureLoader.FromFile(device, "basetext.png");

everything works fine and i get what I want... but I want to load the image from a Bitmap passed to the function... so I try the below method...

Texture testTexture = Texture.FromBitmap(device, srcText, Usage.None, Pool.SystemMemory);

and when i get to the device.DrawIndexedPrimitives i get an error... hrrm!

This topic is closed to new replies.

Advertisement