Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A Texture Atlas Based Text Rendering Crate (that could be integrated) #376

Open
BonsaiDen opened this issue Jun 21, 2023 · 7 comments
Open

Comments

@BonsaiDen
Copy link
Contributor

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

@BonsaiDen BonsaiDen changed the title A Texture Atlas Based Text Rendering Protoype (that could be integrated) A Texture Atlas Based Text Rendering Crate (that could be integrated) Jun 22, 2023
@asny
Copy link
Owner

asny commented Jun 23, 2023

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 Meshes from TextRenderer::build, you can combine them with any three-d material and not just a TextMaterial
  • TextMaterial seems to be very similar to a ColorMaterial?

@BonsaiDen
Copy link
Contributor Author

BonsaiDen commented Jun 23, 2023

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 uses RU8 texture data and that tex_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 be 1.0 for an RU8 texture causing all text to be renderer on a black background instead while also making it completely red :D

Screenshot at 2023-06-23 18-22-48

@asny
Copy link
Owner

asny commented Jun 27, 2023

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 uses RU8 texture data and that tex_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 be 1.0 for an RU8 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 😆

@Nevsden
Copy link

Nevsden commented Aug 11, 2023

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.

@hoijui
Copy link
Contributor

hoijui commented Jan 7, 2024

Would it be possible/ok to add an example using this external crate to three-ds 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.

@asny
Copy link
Owner

asny commented Jan 25, 2024

@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 🙂

@BonsaiDen
Copy link
Contributor Author

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 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants