Text rendering
Idea:
- Create a texture atlas with all the letters (eg using fontdue)
- Add a
TextEffectthat renders a given string (or single letters?) using uvs to index into the texture atlas - Use the effect to render the text into a
Texture2Dusing aColorTarget. - Use the
Texture2Din some material, for example aColorMaterial.
Added text rendering in the most simple way using fontdue to create a text bitmap on request. Also added a simple example to render text on a sprite. Link #312
- Added a
textmodule undercrate::renderer. Not sure, if this is the correct level. - Added a
Fontclass, which reads in a ttf font usingfontdueand can rasterize characters. - Added a
TextEffectholding information on the text and text size to be rendered.
Issues so far with this solution:
- Text is created by accessing
Font::rasterize, which could be expensive. An interim struct to hold all possible characters in atexture atlasis probably the more efficient way. - Not sure, on which level in the crate to implement the text functionality.
- Don't yet know, how to render text on a transparent background, such that the text is the only colorized object in its own visual scope.
@asny Could you direct me towards your solution? Then I can hopefully implement it on my own.
Thanks for starting this 💪 I think it's a good idea to keep it simple, text rendering is a huge topic and not something I envision three-d to excel at. There are plenty of crates that specifically handles text and they can all be combined with three-d relatively easily. First option is to use a crate to render the text into an image which can then be converted into a Texture2D and rendered with three-d. The other option is to use a crate to convert the text into triangle data and then use three-d to render that triangle data.
Then there's the topic of dynamic text vs static text. If we want to handle dynamic text, ie. text that potentially changes every frame, then we'll have to worry a lot about performance. That's why I only want to support static text, at least for now.
So I envisioned this to be a simple integration with fontdue to render static text to a Texture2D which is also very much what you have done 👍 But I still wanted to hear your use-case, if you have one?
Text is created by accessing Font::rasterize, which could be expensive. An interim struct to hold all possible characters in a texture atlas is probably the more efficient way.
As long as we want to handle static text or text that changes rarely, I don't think it's a problem.
Not sure, on which level in the crate to implement the text functionality.
Just keep it were it is, it's fine for now 🙂
Don't yet know, how to render text on a transparent background, such that the text is the only colorized object in its own visual scope.
Use TextureData::RgbaU8 instead of TextureData::RU8 and set the rgb part to some color (for example black) and the alpha value to the output from fontdue. The ColorMaterial that uses the texture needs to be transparent (ColorMaterial::new_transparent).
Also:
- I think it makes sense that it is a functionality on
Texture2Dso instead ofFont::rasterize, we'll haveTexture2D::new_with_text(text: &str, font: &fontdue::Font, size: f32, min_filter: Interpolation, ...). - Remove the
TextEffect. - Note that
Texture2D::new_with_texttakes a whole string as input, not a single letter. - We should also be able to set the color of the text, just another input parameter?
- How do we handle layout? Both meaning layout between letters and layout on the texture.
- Please make the text example similar to the other examples so that it works on web.
- Use
three-d-asset::io::load_asyncto load the custom font so that it works on web. - Use
include_bytes!to load the default font so that it works on web. - Make
fontduean optional dependency.
Changed the struct TextEffect to hold a string instead of a single char. Further changed function rasterize to turn string instead of a char into a CpuTexture. Computation of the correct permutation from bitmap of each char to the unified TextureData::RgbaU8 brought a little confusion but I kinda solved it.
Further investigation needed on how to render the text with a CpuTexture without using Sprites. Also need to look how to stretch text appropriately on the three-d::Texture2D level, once the CpuTexture has been consumed by the ColorMaterial::new_transparent function.
Also, todos from @asny still ongoing.
See #312
Any updates here? It would be nice to have some examples.
Yeah, I think it's abandoned by @Nevsden, but if anybody else wants to do it, feel free to continue from his work. However, since then, @BonsaiDen started a separate crate for rendering text with three-d which I think might be what you're looking for. See #376 for details 🙂