I need to render some formatted text (colours, different font sizes, underlines, bold, etc) however I'm not sure how to go about doing it. D3DXFont only allows text of a single font/size/weight/colour/etc to be rendered at once, and I cant see a practical way to "combine" multiple calls to ID3DXFont::DrawText to do such things...
I looked around and there doesn't seem to be any existing libraries that do these things, but I have no idea how to implement such a text renderer, and I couldn't even find any documentation on how such a text render would work, only rendering simple fixed width, ASCII bitmap fonts which looking at it is probably an entirely different approach that is only suitable for rendering simple blocks of text where Unicode is not important.
If there's no direct3d font renders capable of doing this, is there any other renderers (eg for use in rendering rich text in a normal window), and would rendering those to a texture in RAM, then uploading that to the video card to render onto the back buffer yield reasonable performance?
You tagged this with Direct3D, so I'm going to assume that's the target environment. Otherwise, GDI can handle all this stuff.
Actually, looking at GDI is a good place to start, since it supports this as it stands. With GDI, there is only a single font selected at a time for drawing text. Similarly, there can only be a single text color selected at a time. So, to draw a line of text that contains characters in multiple colors and/or fonts, you have to divide the line up into chunks of characters that all have the same rendering state. You set the state for that chunk (text foreground/background color, text font, text spacing, etc.), then call ::TextOut for that chunk of text, then set the state for the next chunk and draw that, and so-on.
The same principle applied in Direct3D. Each chunk of text may require its own ID3DXFont (or your own font mechanism if ID3DXFont isn't sufficient) and color, etc. You set state, draw text, set state, draw text, etc.
Now, if you want to do your own text rendering, you could do fancier things with a shader, but its probably not worth it unless you have the need for really high-quality typography.
In Windows 7 (back-filled for Vista once Windows 7 ships), you'll be able to use DirectWrite for high quality typography in a Direct3D rendering context (D3D10 and later).
In case of using Direct3D9 or early you really have big problems:
1. You always may use GDI, render your text in the HDC, copy it to the Direct3D dynamic texture and use shader to replace background to transparency by color key for example.
2. Take a look on FreeType library may be you'll find it more suitable for you than GDI, but it really will not be easy.
Any way even if you will find a good way of text rendering you obligotary will have problems with small fonts by reason of ClearType Microsoft technology. At first you will not be able just make a matrix of small symbols to type text from it (because symbol is rendered with using of this subpixel rendering). You will probably need some special shader... or you will be enforced reject to use ClearType, but as i've said before it has bad aftereffects on small fonts. At second this technology is patented by Microsoft
But if you do not need support of Windows XP you may try to use Direct2D with DirectWrite and DirectX10 (I didn't try 11). I tried them and they shown good results, you only should avoid often switching between Direct2D and Direct3D contexts, because it may seriously degrade performance. To render something to your texture you may use ID2D1Factory::CreateDxgiSurfaceRenderTarget function
I suggest measuring the performance of rendering to a bitmap and uploading to a texture.
I suspect that this pretty much what D3DXFont has to do behing the scenes anyway.
You could probably cache letters / phrases etc. if needed
Related
I'm working with OpenGL and Qt. I render a scene in an OpenGLWidget. When hovering over objects in the scene, I would like to display a box near the selected object with some text. I have already implemented the selection of the object.
I thought of two possible approaches.
Place a widget (such as a QLabel) above the OpenGLWidget in
which the scene is rendered.
Render the text in a quad directly in OpenGL.
Which of the two approaches you recommend and you could please give me some suggestions on implementation. Alternatively, you could recommend another approach. Thanks!
Hi #Artic I am not a Qt expert so I can't give you information on widgets, but I can give you some pointers for creating a label with OpenGL. Giving a full implementation is tricky here because it depends a lot on how you want to display the text. But I'll try to outline some of your options.
To render text in OpenGL most people go with a technique known as bitmap fonts, see more here:
https://learnopengl.com/In-Practice/Text-Rendering
The concept of bitmap fonts is fairly straight forward, all characters are pre-rasterized to a texture and then you can sample from each part of the texture depending on the character you need. You build your label out of quads, textured with each part of the bitmap you sample from for each character.
Signed distance fields essentially use the same technique but the pre-rasterized texture of characters are rendered using signed distance fields which deal with some of the issues that standard bitmaps fonts have.
In basic terms, SDF works by generating a special texture, or image, of the font that stores the distance from the edge of each character to its centre, using the colour channels of the image to record the data.
If you use signed distance fields it won't be enough to just sample from your bitmap, fonts rendered this way require extra work (typically done using a shader program) to produce the correct rendering.
Once you have a way of generating a label you can decide if you want to display it in screen space or in world space.
If you want to display it in world space (where the label is hovering over the model or item) you will need to do more work if you want that label to always face the camera and this technique is called billboarding.
You could also render your text "on the fly" if you just want to render some text to the screen in screen space. You can use a library like SDL_ttf.
See: http://lazyfoo.net/tutorials/SDL/16_true_type_fonts/index.php
In this example you use SDL_ttf to render a string of text to a surface with dimensions of your choosing, you can then create an OpenGL texture from that surface and render it to the screen.
Sorry if this information is a bit broad, I would need a more specific question to give you further implementation details.
For an implementation, I would evaluate the pros and cons based on what you need. If you haven't implemented a system for rendering text before it's probably best to stick with something simple; there are more techniques for text rendering than I have listed here such as turning text in to polygons and other libraries which attempt to deal with some of the issues with traditional font rendering techniques but you probably don't need anything complicated.
For a recommendation on which to use I would go with the technique that you feel most comfortable with, typically doing things from scratch in OpenGL will take more time but it can provide you with a nicer set of functionality to use in the future. However if Qt already has something nice for rendering a label (such as a widget that you mentioned) it is probably worth taking the time to learn how to use it as it may yield faster results and you don't want to reinvent the wheel if you don't need to. On that note though doing things from scratch with OpenGL can be very rewarding and greatly improve your understanding since you have to get familiar with how things are done when you don't have a layer of abstraction to depend on. Ultimately it depends on you. Good luck!
You could use tool tips in Qt. The string will appear when the OpenGlWidget is hovered over. You can change the text of the tool tip based on the mouse location in the scene, using the tool tip method showText():
QToolTip::showText(QPoint &position, QString &text, QWidget *w);
There are more options for the showText() method and can be found in Qt's tool tip documentation. Also, here are more examples on how to use Qt tool tips.
I saw that D3DX9 is not recommended by Microsoft and not shipped with Windows SDK.
I would like to adopt.
I'm missing my line drawing utility.
How can I replace ID3DXLine and ID3DXFont in "new" DirectX9?
Generally, lines and fonts are sprites. ID3DXLine and ID3DXFont use ID3DXSprite interface under the hood. (Of course, there are other options too, but sprite approach is the most widely used)
Drawing sprites
So, firstly, you will need either 3rd party or your own sprite renderer. Typically, development of "bedroom" sprite engine, consists of stages:
drawing bunch of simple colored quads (two triangles forming rectangle). There are different techniques, but even simplest "all-in-one vertex buffer" approach is not so bad. More advanced techniques includes instancing, point sprites, geometry shader and tessellation tricks (last two are not applicable in DX9). But don't even try to draw million sprites with million draw calls ;)
Texturing those quads. You will need bitmap loader. If you don't want to use D3DX at all, you can pick open-source FreeImage library for example, of write your own loader.
optimizing rendering using batching. Sort your sprites, to minimize draw calls number and/or minimize context state changes.
optimizing texturing using texture atlases. You will need to solve rectangle packing algorithm (there are already plenty of implementations on web, or pick up you math book) and roll out some kind of texture atlas format.
You can choose on what stage you stop. Later, you can go back and continue.
Drawing lines
Then, for straight lines, you will simply draw a thin rectangular sprite. User will input values such as beginning, end and thickness of line, and you will need to do some simple math to calculate position and rotation of this sprite. Sprite can be just colored or have a texture: for dotted lines, stripped lines, lines with pink fluffy kittens etc. Then, you can implement curved lines as a set of straight lines. You can optionally add sprites to the ends of line, such as arrows.
Drawing text
For text, things can be very complicated (and I will tell only about sprite fonts here):
each character is a little sprite
you draw texture of a letter over it
you have a texture with those letters, and sample it using dictionary. Dictionary is a map of character (or character code) to texture coordinates where it's picture situated, along with additional info, such as spacing, kerning, etc.
you can have pre-baked (offline) texture atlas with all letters of all fonts of all font sizes you need, along with dictionary. Obviously you cannot have all letters of all languages on a planet in your resource cache.
you can bake each character as needed on runtime and add it to your cache (texture atlas + dictionary)
To get characters from font file such as .ttf to a bitmap (image) you can use library. FreeType is a best open-source I know. Parsing fonts yourself can be... complicated.
You can then mix all together and draw lines with text texture. Or draw text surrounded by frame of lines. Or sprite with a text above it. Or GUI. All those stuff will be the sprites.
...or just not bother
If you still using DirectX 9, do you really need to bother with Windows SDK, removing D3DX stuff? Maybe you can continue developing with Direct SDK and D3DX if it works for you? Note, that if, for some reason, you'll decide to move to DX11, there are DirectXTK, which partially replaces D3DX11 stuff. Still, your own, or 3rd party solution will probably be more flexible and suitable for you. There are many others applications of sprites in 3D graphics,, such as billboarding, GUI, particles, etc. And as always, reinventing the wheel is a much fun and positive experience ;)
Hope it helps. Happy coding!
Why not try and use DirectX 11?
Oterhwise OpenGL is supported on almost any platform.
I would recommend trying SDL it has helper methods for most 2D stuff you can imagine.
I want to write a hardware accelerated text renderer using Free Type 2 to load the fonts, find the correct glyphs and their sizes etc.
My plan to do this is to have a large texture containing glyphs (for a given font,size,etc) in video memory, and a table for each texture defining information about the contents of the texture in system memory.
I can then use the table to build a vertex buffer to render the text.
The problem I'm facing is the construction of the texture, it is not practical to create a texture for every glyph in Unicode, there just too many. For Ascii in the past I just built the texture in an image editor and then filled out the table as needed myself in advance, however for this I will need some kind of dynamic system that will get the glyphs needed, but also efficently cache them to avoid repeated uploads of the same glyph to vram...(some sort of least commonly used system I guess)
Another problem is not all glyphs are the same size, I could split the texture up into a grid big enough for the largest glyphs (which I need some way to accurately work out) which makes fitting the glyphs onto the texture easy and replacing them with new glyphs (based on the least commonly used or something), however that leaves a lot of wasted space, but i'm not sure how to more efficiently pack them without running into problems with fragmentation as glyphs are swaped in and out...
Also I assume updating the texture could stall the graphics hardware if the texture is still being used for some previous text, is this a correct assumption and how can I avoid it if its the case?
Text rendering is much complex issue then "pasting" some glyphs... Not just much complex,
it is very complex: kerning, ligatures, spacing, bidirectional text, vowels, and much more...
Why wouldn't you just create a text using normal libraries for text rendering like Pango, create bitmap and display it as bitmap on your 3D object (if I understand what you need).
EDIT: Simple HTML like markup can be rendered with Pango as well: http://library.gnome.org/devel/pango/unstable/PangoMarkupFormat.html
Cairo supports hardware accelerated rendering to many surface types
There is a library called FontForge which is using Cairo for rendering, but i haven't tried it myself. You should check it and let me know how it goes :-)
I want to render font in a way that takes account of the current transforms and similar settings, especially the projection transform and viewport.
I'm thinking that the best way to do that is to have an off screen surface to render the text to, and then render that surface where I really want the text.
However I'm not certain on a number of aspects of this solution.
Is this the best way to go about it at all?
Are there far better free font renderers around that id be better off spending my time with that allow such things. I see alot of people complaining about the d3dx font interfaces for various reasons, but never a link to a better unicode capable renderer...?
Is there any advantage to useing certain surface formats and/or surface sizes (eg always using the smallest possible rather than some standard large one, which requires the extra step of trying to work the size out...)
Yeah, render to texture and then drawing a textured quad to orient and position the text is going to be the easiest way to realize this functionality.
As for D3DX text renderers, it really depends on which SDK you are using. DirectWrite (only for Windows 7 and Vista) will provide a higher quality text rendering approach for applications that need high quality text rendering in a manner that is interoperable with Direct3D.
You can of course do your own rasterization. There are font rasterization engines out there that are open source that could be repurposed for this need, but we're talking tons of coding here for a benefit that may not be distinguishable enough to warrant the development expense.
Having said that, there's a completely new alternative available to you with Direct3D and shaders, provided that you have access to the glyph outlines as curve data. The idea is to use the shader to rasterize the text and store the curve definitions in the vertex stream and associated textures. Try looking at this paper, which describes the technique.
Does anyone have any tutorials/info for creating and rendering fonts in native directx 9 that doesn't use GDI? (eg doesn't use ID3DXFont).
I'm reading that this isn't the best solution (due to accessing GDI) but what is the 'right' way to render fonts in dx?
ID3DXFont is a great thing for easy to use, early, debug output. However, it does use the GDI for font rasterization (not hardware accelerated) and there is a significant performance hit (try it, its actually very noticable). As of DirectX 11, though, fonts will be rendered with Direct2D and be hardware accelerated.
The fastest way to render text is using what's called "Bitmap Fonts". I would explain how to do this, except that there is a lot of different ways to do implement this technique, each differing in complexity and capability. It can be as simple as a system that loads a pre-created texture and draws the letters from that, or a system that silently registers a font with Windows and creates a texture in memory at load-time (The engine I developed with a friend did this, it was very slick). Either way, you should see a very noticable performance increase with bitmap fonts.
Why this isn't a good solution?
Mixing GDI rendering and D3D rendering into the same window is a bad idea.
However, ID3DXFont does not use that. It uses GDI to rasterize the glyphs into a texture. And uses that texture to render the actual text.
About the only alternative would be using another library (e.g. FreeType) to rasterize glyphs into a texture, but I'm not sure if that would result in any substantial benefits.
Of course, for simple (e.g. non-Asian) fonts you could rasterize all glyphs into a texture beforehand, then use that texture to draw text at runtime. This way runtime does not need to use any font rendering library, it just draws quads using the texture. This approach does not scale well with large font sizes or fonts with lots of characters. Also would not handle complex typography very well (e.g. where letters have to be joined etc.)
With DirectX, the correct way to render standard fonts is with GDI.
However, IF
You want to support cross platform font rendering
with proper support for internationalization - including far eastern languages where maintaining a glyph for every character in a font is impractical
and/or You want to distribute your own fonts and render them without "installing" them...
Then libfreetype might be what you are looking for. I don't claim its easy: Its a lot more complex than using the native font api.
Personally I think that ID3DXFont is the way to go.
If you really wanted to make your own font routines, I suggest you look at:
http://creators.xna.com/en-us/utilities/bitmapfontmaker
You can use this to create a bitmap with all the characters printed on it. Then its just a matter or loading the texture and blitting the relevant chars onto the screen at the right place. (This is what XNA uses for its font drawing)
Its a lot more work, but you don't need the font to be installed on the target PC, and you have the advantage to being able to go into photoshop and edit the font appearance there.