I recently started learning DirectX programming in C++ and I've encountered a minor problem.
The thing is that my excercise requires me to change colors in a DirectX application from one to another. I have a function which does that:
void render_frame(void)
{
// start the random generator
srand(time(NULL));
// clear the window to random color
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(rand() % 255, rand() % 255, rand() % 255), 1.0f, 0);
// begin/end/display scene
d3ddev->BeginScene();
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
It works, but it's dependant on the time() delay and I wonder if there's a better counterpart in Direct3D library. For example if I could call this function in order with specific color and delay in chain like this:
void render_frame_red(void);
delay(1000);
void render_frame_blue(void);
delay(1000);
I know that function Sleep() exists in standard library, but it literally freezes my application window (I can't interact with it during the delay). Maybe I can set time to different tickrate so it'll update as frequently as I want it to?
I know it's a small thing and I would probably figure it out later on my journey with 3D programming, but it wouldn't hurt if I knew more about how things work in DirectX.
The general model for Direct3D is to render frames "as fast as possible" and then have time-based operations in your program deal with animation. Traditional GDI-style drawing only paints 'on-demand', which you can do with Direct3D but makes things harder.
In other words, use clock-time instead of frame-count to control animation and effects. For a good timer solution for Direct3D rendering, see this blog post.
BTW, don't invest your time in learning legacy Direct3D 9 which relies heavily on supporting code from the deprecated DirectX SDK and requires the legacy DirectSetup to deploy the ancient helper library D3DX9 (see MSDN). Use DirectX 11. See DirectX Tool Kit.
Related
I'm currently working on developing an internal ui for games (just like imgui) and am stuck on the quality of fonts when they are rendered through DrawText (ID3DXFont), I've tried to use DrawTextA and link a sprite to the rendering of the font but it doesn't look like there is a difference. When comparing it to imgui it seems as if the quality of the text is much higher and is anti-aliased properly, although when using ANTIALIASED_QUALITY when creating the font doesnt seem much like the anti-aliasing done in imgui at all. I'd like to make my text look at good as imgui's as im really fed up with ID3DXFont looks but am wondering on how to make it look better.
Here's some examples between ID3DXFont and Imgui (both fonts are Arial Bold and rendered with size 23)
ImGui (in d3d9):
ID3DXFont:
this is what my text rendering looks like:
ID3DXSprite* Sprite = nullptr;
D3DXCreateSprite(Device, &Sprite);
Sprite->Begin(D3DXSPRITE_ALPHABLEND);
Font->DrawTextA(Sprite, Text.c_str( ), Text.length( ), &Size, DT_NOCLIP, D3DColor);
Sprite->End( );
Sprite->Release( );
and my font initialization:
D3DXCreateFont(Device, 23.f, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, "Arial", &Font);
The first thing to say is that Direct3D 9's ID3DXFont interface is extremely old at this point, dating back to 2002 or even earlier. D3DX9, D3DX10, and D3DX11 are all deprecated as is the legacy DirectX SDK itself. See this blog post.
For Direct3D 10 or later, the recommended solution for high-quality, scalable font rendering on DirectX surfaces is DirectWrite (using Direct2D to render). The interop is a little complicated prior to DirectX 11.1, but is pretty simple with it (Windows 7 SP1 + KB2670838 installed, Windows 8.x, and Windows 10). See Microsoft Docs for DX11 / DX12.
The ID3DXFont solution as well as SpriteFont in the DirectX Tool Kit for DX11 / DX12 capture the TrueType glyphs into a texture at a specific font-size and then render them as a sprite-sheet. This is very fast, but does not have the scaling behavior of a vector-font solution like DirectWrite, FreeType, etc. That said, sprite-sheet fonts tend to look great as long as you are rendering them at the same resolution as they were captured at.
The images you show above are not 23 points high so they are going to squash a bit and you'll notice the difference between FreeType and a sprite-sheet solution in that case.
The D3XD9 ID3DXFont solution is a little more primitive than SpriteFont. D3DX9 always uses D3DFMT_A8R8G8B8 for the captured texture. SpriteFont can use a DXGI_FORMAT_R8G8B8A8, DXGI_FORMAT_B4G4R4A4, or DXGI_FORMAT_BC2_UNORM encoding. SpriteFont is also optimized for premultiplied alpha rendering.
So im currently coding a snake game , and i need to draw the first pixel that indicates the head of the snake (positioned in the middle of the software). But i can't seem to find any function that does drawing on the screen . I've tried using DrawRectang and DrawPixel.
Any help ples?
wxWidgets has capabilities to custom draw a widget/window (or a small invalidated part of one) through it's own drawing API.
This is usually used for customized buttons or other controls, graphs, etc. You can handle EVT_PAINT (wxPaintEvent) where you can create a DC ("Device Context"). As well as on creation or size changes, you can force a redraw with wxWindow::Refresh or wxWindow::RefreshRect (for a small part). You might do so using a timer.
Note that the performance and capability is fairly limited. You can use OpenGL or Direct3D , or various high level libraries with wxWidgets, the native platform window handle is obtainable through wxWindow::GetHandle.
Using Windows Image Component (WIC), I want to do the following for my windows desktop application (Direct2D/C++ with Windows 7 SP1 - Visual Studio 2013)
Choose any type of RenderTarget (Direct2D Hwnd/Bitmap/WICBitmap -
etc) for drawing
Create a empty bitmap (D2D1Bitmap or IWICBitmap -
whichever applicable)
Begin draw - Fill colour, draw some lines and ellipses -
End draw ==> (All in the Bitmap)
At some point of time, I need to
save the drawn content in the bitmap as an image in my computer
Place the bitmap in the x1,y1 (top left - xy coordinates) and x2,y2
(bottom right - xy coordinates) of the render target. Because the
rest of the space of the window would be used by toolbar.
How do I achieve this using C++/Direct2D?
GDI+ Code for my functionality:
Bitmap* pBmp = NULL; //create null or empty bitmap
Graphics* pGrBuf = NULL; //initialise graphics to null
pBmp = new Bitmap((INT)rectClient.Width, (INT)rectClient.Height);
pGrBuf = new Graphics(pBmp);
On this Graphics, I could always draw Lines, Rectangles, etc..
pGrBuf.DrawRectangle(....)
pGrBuf.DrawLine(...)
In the end, for achieving point number 5
//leave some space (30, 30 in xy co-ordinates) for putting the toolbox in the top
pGrBuf.DrawImage(m_pBmp, 30.0f, 30.0f);
The code for point 4 is intentionally omitted.
The question have a simple, unambiguous answer, but there are some details that you should (re)consider.
Direct2D is not a panacea framework that will easily outperform others. It's not very clear what are your drawings about and whats their purpose, but there are cases where Direct2D usage is not very appropriate. If you replace GDI(+) with D2D, some of your sufferings will be:
(officialy) limited OS support, according to the DirectX version and/or the functions you will use. You will have to forget about Windows XP, (very possibly) Windows Vista and (less possibly) Windows 7
the performance (compared to GDI+, GDI) is not always greater. Mainly depends from the way and the purpose you use D2D. There are cases where D2D has very poor performance (usually wrong usage or misunderstood concepts).
But also, the advantages that Direct2D could provide are countless.
Roughly said, Direct2D is nothing but a wrapper around Direct3D. It was introduced with the DirectX 10 and its usage was very similar to GDI(+). But with DirectX 11(1), the Direct2D "principles" were changed and now its more D3D-like. It adds another approaches and drops old ones. It could be a little bit confusing at first. Confusing, also because all the tutorials, articles and whatever D2D resources (including MSDN) in the web are mixed up between the D2D versions. Some of them are for the old version and recommend one thing (approach), other describe the new version.
Anyway, I recommend the new version - ie Direct2D 11.1.
To your question...
The "RenderTarget" is a concept from the "old" D2D. The new one is a DeviceContext
The DeviceContext has a target that could be a D2D1Bitmap(1) - offscreen one, a swap chain's back buffer.
The most typical drawing approach is to call drawing functions within a DeviceContext.BeginScene --- DeviceContext.EndScene block. The drawing functions are very similar to the GDI(+) ones.
There are several ways to do that. You can do it with the help of WIC. Also you can copy your D2D1Bitmap data to a DIBBitmap or you can even (re)draw it over a GDI context.
There is a function DeviceContext.DrawImage, but the way you will do it depends on many things. For example, you could have two bitmaps, that are drawn over two different HWnd (one for the toolbar, another one for the other drawing).
Here are some resources that could help you:
What is Direct2D for
Drawing a rectangle with Direct2D
Very well explained guide about migrating to Direct2D 1.1
Answer to another question here, related to Direct2D, but explains in short the way you should draw to a HWnd
I am training in using the allegro library with c++ but I am getting an issue, while using large images for parrallax backgrounds i get a constant sort of load/glitch scrolling down the screen, making all my images flicker for a bit, is there a way to load backgrounds without having such an issue? The flicker does not appear when I try to print the screen.
Thanks
The flickering is most likely a result of you redrawing your scene, and the monitor refreshing partway through.
The cure for this is to use double buffering. Read this:
http://wiki.allegro.cc/index.php?title=Double_buffering
There is another artifact called 'tearing', which is caused by blitting your buffer during a refresh cycle. This is generally solved by waiting for a vertical sync (retrace) and then drawing, but that's a little oldschool now that most of us use libraries such as OpenGL or DirectX to talk to our graphics hardware.
Nevertheless, Allegro provides a function that waits for the vertical retrace to begin, which is the time at which you can safely blit your buffer without worrying about tearing. See here:
https://www.allegro.cc/manual/4/api/graphics-modes/vsync
I cannot promise that this is the solution, but looking at your code, I don't understand why you are creating multiple buffers.
bufDisplay = al_create_bitmap(WIDTH, HEIGHT);
buffer = al_create_bitmap(WIDTH, HEIGHT);
Unless you are doing some type of special effect that requires buffers, they are unnecessary. Allegro 5 already provides a double buffer with default settings.
Just draw everything to the default target bitmap (the display's back buffer), and then al_flip_display().
If you want to center or scale your output to a different sized window, you can usually just use transformations.
I don't know why you are calling Sleep(8).
If using Windows, you could switch to using OpenGL (set the ALLEGRO_OPENGL display flag).
You should try other Allegro games and demos (plenty come with the source) to see if it's a problem on all of them.
I am learning to use the allegro library right now and when using the set_gfx_mode function if I use GFX_AUTODETECT_FULLSCREEN for the first argument the window will go fullscreen when running the compiled application, but after about the first second of running, all the colors change. Using any other graphics mode this doesn't happen, but on two separate machines the colors change just after changing to fullscreen mode. Has anybody else seen this happen before? I can't find any discussion on this problem at all.
I am using the pre-compiled allegro 4.4.2 library for visual studio 2010 and running windows 7.
Allegro 4 is old and uses APIs that are no longer very well supported by modern operating systems. The full screen mode is going to be buggy, especially on 8-bit graphics. The best way to get a reliable full screen is to honor the user's current desktop settings:
int w, h;
get_desktop_resolution(&w, &h);
set_color_depth(desktop_color_depth());
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, w, h, 0, 0);
Then your application will need to center/scale the drawing. It's not really that difficult, just draw everything to an intermediate buffer that is the width/height of your native game, and then stretch blit it to the appropriate screen size.
All that said, you should really be learning Allegro 5 as it is designed to work on today's hardware and operating systems, including iOS and Android.