Sign in to follow this  
Guest christian

gauge programming using directx

Recommended Posts

I just had a browse through the forums how to draw a gauge using directx, but couldn't find much useful info. I'm an opengl pro, but haven't done anything in dx yet, so I'm a bit lost...It seems I can grab the device context using IDirect3DSurface9:GetDC() and then paint over that. I need to play around a bit to see how this works, but if anyone has a code example that would be greatly appreciated. I'd to use this to do some alpha blending and possible extend into shaders at a later stage. I read though that using IDirect3DSurface9 alpha channels won't be supported. If this is the case, what do I use instead then?There was some earlier discussion how using DX9 may be slower due to context switching? Anyone has experience in this?I hope, someone can kindly share some code on how to set up DX9 right. I'm quite an experienced programmer, but I'm a bit lost with DX9 related things, since usually you'd create your own window, etc, but in this case one would really like to tap into the FS9 render loop if possible.Cheers, Christian

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

I'm in the same boat. The actual drawing process seems to be simple enough, but I'm stumped when it comes to acquiring the surface to draw on. Like the OP, I'm about to just start trying random things but if anyone could give us a push in the right direction I'd appreciate it :)I just spent about 2 hours mired in Google and MSDN and found absolutely nada. This topic has been posted several times but nobody's ever answered. Surely it's possible, else people wouldn't talk about it all the time ;)

Share this post


Link to post
Share on other sites

I dont't know to use directx (for drawing), but a DC to draw to, can be provided by using a MAKE_STATIC with the IMAGE_CREATE_DIBSECTION bit set. I use it for GDI and GDI+ drawing.Arne Bartels

Share this post


Link to post
Share on other sites

Thanks, ArneI'm starting to think that the gauge DC provided by FS is limited and one may have to create a new DC and swap contents later. This will need some testing on performance issues...Cheers, Christian

Share this post


Link to post
Share on other sites

I'm making *slow* progress with DX9, to the point where I can draw on a panel in DX9 (2D or 3D). Getting a drawing surface in DX is not technically the problem.My current hurdle is to suppress the conflict between two paints: the paint trigger in FS fires a DX paint which in turns triggers an invalidate (or a repaint). If you control your paint, no problem, but in this case, the panel is told when to paint and most of the painting (even GDI+ that draws to a bitmap but is rendered by FS) is controlled by FS.The bottom line: two sets of renders, and even a transparent render causes flicker to occur.More on this later, right now I'm still in the trial and error mode. But, the good news is that it's possible to at least draw concurrently and only in the panel.Any ideas on how to suppress the internal FS repaint cycle would be useful. The idea would be to fire the PREDRAW event, but then kill any subsequent paint.Why go through this? The benefits of using DX are definitely not coding, but it lies in speed (GDI+ is notoriously slow), and to me, the ability to render things in full 3D and have lighting/transforms not available in GDI+.

Share this post


Link to post
Share on other sites

I haven't actually done any experiments myself yet (and I'm still contemplating the use of opengl), but I got some ideas:1 - from what I read you can transfer your drawing do the DC using blitting, but this has some limitations...2 - you could maybe draw into a bitmap and transfer that in the paint routine. The panel SDK let's us grap both the DC and the bitmap handle.Would any of this help?>Why go through this? The benefits of using DX are definitely>not coding, but it lies in speed (GDI+ is notoriously slow),>and to me, the ability to render things in full 3D and have>lighting/transforms not available in GDI+.Completely agree, and that's why I'd like to go down this route as well. We can even use shaders which will make use of modern graphics card features for some nice advanced effects.Cheers, Christian

Share this post


Link to post
Share on other sites

The blitting is done normally for textures - not sure if there's a speed advantage by doing this because you still need to BLT using a GDI+ graphics context, but it does have its points.I've played with stealing the WM_PAINT or WM_ERASEBKG for the panel window but that doesn't seem to work very well either.The "normal" way this is done is by subclassing the paint routine and replacing it with your own, but in this case, subclassing the paint routine for just that window is proving to be more of a challenge, until I hack at it some more...Also, I need to hunt down why the window handles returned by the FS callback routine don't seem to agree with the window handles spy++ reports. So, situation normal so far . Perhaps GDI+ is the way afer all.

Share this post


Link to post
Share on other sites

I did a bit more research without actually implementing something.It looks to me as if one has to create a render context and draw to a bitmap instead of the screen, and then use the bitmap either directly or blt it onto the device contect using GDI (I suspect if one uses the bitmap handle directly, FS will blt it in the paint update). This is using opengl. I don't know any directx, so I'm not sure if it draws to a render context or the device context directly. However, I'm relatively convinced that this is how FS does this internally also, ie use DX to draw to a bitmap and then use GDI to render that bitmap.You want to draw directly onto the screen, but obviously, as you figured out, you get a conflict with the FS update routine. You may put you drawing code into post_draw and see what happens, but drawing to bitmap makes more sense to me, since you still leave the drawing to FS. Since you can draw anything you want to the bitmap, you still make use of DX speed and features, it's just the very last draw that uses GDI amd although it is slower, it is still fast enough, when using the standard make_static etc commands, we're using GDI...Cheers, Christian

Share this post


Link to post
Share on other sites

I just jump in, as I've already managed to use OpenGL to draw a gauge and it reminds me some of the caveats encountered.The point in having DX draw to a bitmap then to blit the bitmap to the gauge "STATIC" bitmap, is that I think this is far from the fastest.Maybe someone can confirm here, but to my knowledge, when using OpenGL or DX to draw to a bitmap, this bitmap is not in the video card memory but in the system memory. In this case, you loose a lot of the hardware accelerated features of the card and the speed benefit may not be this much interesting.You can also as far as I remember draw to surfaces in the video card memory, but then, this is at the expense of the main FS 3D rendering engine (video card memory is already highly stressed by FS), and when you will blit to the gauge, then the video card as to transfer from one memory (video) to the other (system) and later on the composited panel is blitted back to the video memory...GDI and GDI+ suffer the same in the context of FS9.

Share this post


Link to post
Share on other sites

After playing with this a little more, I'm finding thus far is that bliting the surface (video memory, off screen - same issue), to a target window - the panel in this case, runs into a problem with the internal painting - causing this flicker. Renders fine, the problem is that the moment the buffer is moved into display, FS triggers a repaint (I even tried transparent bitmaps with the hope it wouldn't). Interestingly enough, it's not sending a WM_PAINT either, so the render would appear to be ran inside DX as well. It appears to me that the best way to proceed is to simply stop FS from processing that panel (the "Draw_Routine" in GAUGEHDR looks interesting from that standpoint).The other is to overlay a window that FS doesn't control but this may cause new issues in full screen mode with DX.Or tap into the rendering pipeline FS uses. Seems overly complex for what should be a reasonably simple subclassing problem.Progress is slow but I'm not giving up just yet.

Share this post


Link to post
Share on other sites

Would you mind sharing some code? I'v tried setting this up yesterday, but my code fails right at the start already.In my callback, I'm using the HDC from MAKE_STATIC, since it seems to be a DIB section already, so I don't seem to need to create one. However, my code fails with ChoosePixelFormat, complaining that it doesn't have a valid handle (HDC I guess). Any idea what's wrong?Fair points about the speed, but FS9 has to do this internally somehow, so all we need is just to be faster (or as fast with more sophisticated features, such as alpha blending). I'd really appriciate if you could post some relevant code snippets on how you got it working...Here's my callback:void FSAPI m803_callback ( PGAUGEHDR pgauge, SINT32 service_id, UINT32 extra_data ){ PELEMENT_STATIC_IMAGE pelement = (PELEMENT_STATIC_IMAGE)(pgauge->elements_list[0]->next_element[0]); HGLRC hrc ; //OpenGL Rendering Context switch (service_id) { case PANEL_SERVICE_PRE_INSTALL: { HDC hdc = pelement->hdc; PIXELFORMATDESCRIPTOR pfd ; int pixel_format; int res; memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; pixel_format = ChoosePixelFormat(hdc, &pfd); res = SetPixelFormat(hdc, pixel_format, &pfd); hrc = wglCreateContext(hdc); } break; }}Here's the MAKE_STATIC:MAKE_STATIC( m803_line, BMP_CLOCK_LINE, NULL, NULL, IMAGE_USE_ERASE | IMAGE_CREATE_DIBSECTION, 0, 11, 55)PELEMENT_HEADER m803_line_list[] ={ &m803_line.header, NULL};Thanks for any help.Christian

Share this post


Link to post
Share on other sites

Maybe if you put some basic code up I could comment. Are you using the HDC from a MAKE_STATIC? If not that may be the problem?Christian

Share this post


Link to post
Share on other sites

I'd have to dig in an old and rusty CD!I've looked around but have not found my sources back :-(I remember using a memory DIB to draw to, then using GDI blit to render the OpenGL drawn DIB to the FS static element.Hope this helps!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this