A Texture Atlas Based Text Rendering Crate (that could be integrated)
Opened this issue ยท 8 comments
Hey there,
first of all thanks for all the effort spend on the library! I've been looking for something to replace the outdated kiss3d from time to time and I'm quite happy to have found three_d :)
Now, something I wasn't to happy about though was the lack of text rendering; however, talk's cheap to I whipped up a prototype which uses a texture atlas based backing texture for the different font sizes and features coloring and alignment.
It currently lives on my gitlab and the README goes into a bit more detail on the technical architecture: https://gitlab.com/BonsaiDen/three-d-text-renderer
The example also contains a lot of comments on how to use it.
Now, the primary question is whether or not you would be interested in integrating a text renderer directly with the library or if it should stay as a standalone library, in the first case I could spend the time to add all the required documentation and stuff (and likely bikeshed a few of the names), in the latter the lack of crates.io namespaces would probably still need some coordination on the name of that library as I don't want to snatch a potential three-d-text-render
crate without consulting you first.
In any case, thanks again for all the work put into the project.
Best regards,
Ivo
Hi @BonsaiDen
Thanks for the kind words, I'm glad you like three-d
๐ฅณ
Actually, you are not the first to try to add text rendering to three-d
, there's both #312 which seems to be abandoned and there was also another attempt earlier that I can't find right now. The biggest concern with adding text rendering, is that it's a huge topic and there's a lot of ways to do it. So either three-d
should support it all, which is a huge effort, or it should support a simple way of rendering text, or it should be outside the scope of three-d
. I'm not in favour of the first, and I think it's a really good idea to keep it outside of three-d
, at least for now!
So I think it's a great initiative and I really like the code, it's a great start ๐ At some point, it might make sense to integrate it into three-d
, but for now I'm all for keeping it in its own crate. And you are more than welcome to use the three-d-text-render
name ๐
A couple of technical suggestions (and it is suggestions, you don't have to use them, and I might also be wrong):
TextRenderer
is not really a renderer, it's more of a text generator since it generates the meshes needed for rendering.- If you return an iterator over the
Mesh
es fromTextRenderer::build
, you can combine them with anythree-d
material and not just aTextMaterial
TextMaterial
seems to be very similar to aColorMaterial
?
Hey @asny,
Thanks for the Feedback!
Yes, I can totally see that folks would ask about SDFs etc. once you add any kind of text rendering to begin with, so I will probably polish the code (quite) a bit and then publish it as an easy to find crate while clearly stating in the README that it's not an "official" crate and that there will be no support from your end :D
Regarding your suggestions:
- Yes the name is not good, I'll probably go with
TextModelBuilder
or something like that - Currently the material is managed internally by the caches for the individual font sizes, so that the backing cpu texture is only uploaded when it actually changes, this basically has the effect of "copy on write" and you can create a lot of static text geometry upfront that will share the same uploaded texture, if you would want to bind them to your own materials you'd need to return a pair of the Mesh and the CpuTexture and then have do the "efficient" upload in the application, in theory there could be a second API that does this, but that would also be prone to breakage or limit the internals of the library with regards to optimisation
- The main difference is that
TextMaterial
usesRU8
texture data and thattex_color.r
in the fragment shader is used for setting the alpha (this saved 3/4 of the memory for the font atlases)- With a
ColorMaterial
,tex_color.a
gets used in the fragment shader, but that will always be1.0
for anRU8
texture causing all text to be renderer on a black background instead while also making it completely red :D
- With a
Thanks for the Feedback!
No problem, thanks for your hard work ๐ช
Yes, I can totally see that folks would ask about SDFs etc. once you add any kind of text rendering to begin with, so I will probably polish the code (quite) a bit and then publish it as an easy to find crate while clearly stating in the README that it's not an "official" crate and that there will be no support from your end :D
Sounds like a great plan ๐ Please let me know when you have released it, and I add a link to it from the three-d
README ๐
- Yes the name is not good, I'll probably go with
TextModelBuilder
or something like that
Naming is hard ๐ฌ It seems like you ended on TextBuilder
, I like that ๐
- Currently the material is managed internally by the caches for the individual font sizes, so that the backing cpu texture is only uploaded when it actually changes, this basically has the effect of "copy on write" and you can create a lot of static text geometry upfront that will share the same uploaded texture, if you would want to bind them to your own materials you'd need to return a pair of the Mesh and the CpuTexture and then have do the "efficient" upload in the application, in theory there could be a second API that does this, but that would also be prone to breakage or limit the internals of the library with regards to optimisation
Yeah ok, I see. The texture defines the geometry, so you cannot generate the geometry in a vertex shader alone. You could use a deferred approach to render the geometry into buffers first and then apply the material in the second pass, but that would be complete overkill since users in 99.9% of cases would just want to apply a uniform color to the text. So I think your approach is good ๐ Maybe you can return a new struct that encapsulates the Mesh
and TextMaterial
and which implements the Object
trait? So instead of returning an iterator over Gm<Mesh, TextMaterial>
, TextBuilder::build
would return an iterator over this new struct (Character
?). This would be similar to for example axes which is a specific combination of Geometry
and Material
. Similarly, each character is a combination of a Mesh
geometry and a TextMaterial
material. Also, the TextMaterial
really also contains geometry information, so it would maybe be best not to expose that and just be able to set a color on Character
? Again, this is only suggestions ๐
- The main difference is that
TextMaterial
usesRU8
texture data and thattex_color.r
in the fragment shader is used for setting the alpha (this saved 3/4 of the memory for the font atlases)
I got it, the TextMaterial
texture actually contain the geometry ๐
- With a
ColorMaterial
,tex_color.a
gets used in the fragment shader, but that will always be1.0
for anRU8
texture causing all text to be renderer on a black background instead while also making it completely red :D
Yeah, I see, that won't work ๐
I am happy to see, @BonsaiDen is also trying to implement the text feature. Due to some distractions I could unfortunately not continue on the feature implementation.
Would it be possible/ok to add an example using this external crate to three-d
s examples folder, @asny?
I understand it would mean possible issues for you as the three-d maintainer, in case the external lib becomes unmaintained.incompatible with the latest changes in three-d
, but for us users it would be optimal.. that is how we'd most likely find it.
@hoijui Yeah, I think that is ok since it's a crate that is specific to three-d
. I can always remove the example or integrate the crate into three-d
if it becomes unmaintained at some point ๐
Hey there,
seems like I never got around to publishing the crate (ended up bike shedding the API and then life got busy), I'll have a look and update the dependencies if required and publish it to crates.io this weekend :)