LWJGL / lwjgl3

LWJGL is a Java library that enables cross-platform access to popular native APIs useful in the development of graphics (OpenGL, Vulkan, bgfx), audio (OpenAL, Opus), parallel computing (OpenCL, CUDA) and XR (OpenVR, LibOVR, OpenXR) applications.
https://www.lwjgl.org
BSD 3-Clause "New" or "Revised" License
4.83k stars 642 forks source link

Implement bindings for msdfgen-core for generating MSDF sprites at runtime #977

Closed KitsuneAlex closed 4 months ago

KitsuneAlex commented 6 months ago

This PR aims to add support for the excellent msdfgen library, which allows the generation of (M)SDF glyph sprites at runtime using an easy-to-use interface. It includes a hand-written API wrapper to allow the JVM to interact with the library's C++ API.

I'm making this a draft PR for now since i want some feedback and i still want to add documentation to the bindings once i'm adding it to the C-API.

For anyone wanting to test the bindings themselves, you can download the latest builds here until they're available.

Cheers.

KitsuneAlex commented 6 months ago

I consider my C-API done so this would be ready for review @Spasi, regardless whether the msdfgen-core PR gets merged or not :)

KitsuneAlex commented 6 months ago

Okay found a little issue on macOS/aarch64 while building different platforms. Need to build the binding module as C++ as it seems.

KitsuneAlex commented 6 months ago

Tested linux-x64, macos-arm64, macos-x64 and windows-x64.

KitsuneAlex commented 6 months ago

Spotted an issue, fixed by defining handle types using the handle extension. My bad.

KitsuneAlex commented 6 months ago

I am adding some more bindings to their extension API. This would allow directly loading glyph shapes from font files using FreeType. How would you like this to work in the best case @Spasi? Is there an easy way to statically link a LWJGL module against a native library? Otherwise i'll go for custom build arguments.

Update: I resorted to using the per-platform module build configurations. On Windows, i'll use vcpkg to get FreeType.

Spasi commented 6 months ago

The best case for me would be to avoid the dependency entirely. Freetype is a pita to build properly, because of the interdependency with HarfBuzz. Statically linking it would also mean a bigger binary.

Ideally, LWJGL users would be able to use the existing Freetype bindings for this. The msdfgen module would call whatever it needs to call at runtime, assuming both modules are available.

KitsuneAlex commented 6 months ago

The best case for me would be to avoid the dependency entirely. Freetype is a pita to build properly, because of the interdependency with HarfBuzz. Statically linking it would also mean a bigger binary.

Ideally, LWJGL users would be able to use the existing Freetype bindings for this. The msdfgen module would call whatever it needs to call at runtime, assuming both modules are available.

That's also why i was asking in the first place. FT is a pain to deal with. Is there a way i can just depend on the lwjgl-freetype natives somehow?

Spasi commented 6 months ago

Hard to say, it would likely involve platform-specific complexities. Isn't the extension API simple enough that it'd be easier to port it to Java/LWJGL?

KitsuneAlex commented 6 months ago

Hard to say, it would likely involve platform-specific complexities. Isn't the extension API simple enough that it'd be easier to port it to Java/LWJGL?

It's quite a bit of code, so i just wanted to make sure if there's an easy way. But in this case, i'll still do it. I'll port the font importer to Java and include it in the binding sources. I can include some utils for blitting MSDF bitmaps to BufferedImages too while i'm at it.

KitsuneAlex commented 6 months ago

I will test the implementation in my current project now and let you know if i'm done with the bindings so you can start an actual review if you want @Spasi :)

KitsuneAlex commented 6 months ago

I removed the utils again because i think it's not really worth the dependency on java.desktop for BufferedImage.

KitsuneAlex commented 6 months ago

@Spasi Small update: making good progress, i'd say the API is pretty much feature complete now for normal use. However, i still want to add the FreeType interop back in. I am currently rewriting a part of msdfgen-core to allow it to use FreeType interop without having to link against it so i can integrate it with lwjgl-freetype on the JVM side. The FreeType related calls within msdfgen will be made using function pointers.

KitsuneAlex commented 6 months ago

Proof of concept works for me. Gonna add Windows support and integrate it into LWJGL.

KitsuneAlex commented 6 months ago

I'm quite happy with this design. You can easily plug LWJGL FreeType into LWJGL msdfgen now @ runtime with minimal glue code. Let me know what you think @Spasi image

KitsuneAlex commented 6 months ago

Tested latest changes on windows-x64, linux-x64, macos-x64 and macos-arm64. Looks good to me. I'm done with this from my end @Spasi ^^

KitsuneAlex commented 6 months ago

The C-API is now part of my permanent msdfgen fork, since the author is not interested in merging it. You can find my new repository here.

KitsuneAlex commented 5 months ago

Do you want me to update this to master or can i just leave it until it is merged? ^^

Spasi commented 5 months ago

No worries, I'll rebase it and resolve any conflicts when I merge it (soon, I promise!).

KitsuneAlex commented 5 months ago

No worries, I'll rebase it and resolve any conflicts when I merge it (soon, I promise!).

No hurries, didn't wanna come off as pushy, but there's projects where this is expected from the PR author ^^ Thank you very much.

Spasi commented 4 months ago

Hey @KitsuneAlex,

I just pushed the msdfgen branch. It's this PR but with everything squashed to a single commit and rebased to current head. I did the following changes:

Please review and let me know if it's ready to merge. I will force-push the branch to this PR, so if you'd like to keep the commit history, make sure you have a copy of it.

KitsuneAlex commented 4 months ago

Hey @KitsuneAlex,

I just pushed the msdfgen branch. It's this PR but with everything squashed to a single commit and rebased to current head. I did the following changes:

  • Removed all Unsafe modifiers, replaced with Check where applicable. The unsafe modifier on a struct type makes the generator assume that it's an array of structs of unknown length. This made such parameters have a type of MSDF<Type>.Buffer instead of just MSDF<Type>.
  • Split msdfgen-ext to a separate class.
  • Added the FontCoordinateScaling parameter of msdf_ft_font_load_glyph.
  • Added sample code (org.lwjgl.demo.util.msdfgen.HelloMSDFGen).
  • Some minor cleanup/fixes.

Please review and let me know if it's ready to merge. I will force-push the branch to this PR, so if you'd like to keep the commit history, make sure you have a copy of it.

Will check it out in a moment, thank you so much <3

KitsuneAlex commented 4 months ago

@Spasi Definitly approved, looks very good to me :)

Spasi commented 4 months ago

Thank you @KitsuneAlex!

KitsuneAlex commented 4 months ago

Was a pleasure! :)

Desoroxxx commented 3 months ago

It seems like this binding missed a critical method, see: https://github.com/Chlumsky/msdfgen/issues/105

This makes it unusable for advanced text rendering, unless I missed something. If I did not miss something, could the bindings be updated or should I make a dedicated issue for it?

KitsuneAlex commented 3 months ago

@Desoroxxx See this example. This shouldn't cause you any issues. If it actually does, let me know and i'll update the bindings :)

Desoroxxx commented 3 months ago

@Desoroxxx See this example. This shouldn't cause you any issues. If it actually does, let me know and i'll update the bindings :)

My issue is when using the binding with Harfbuzz, I need to render more than unicode glyphs

KitsuneAlex commented 3 months ago

OH, now i understand what you mean :) I will write a patch the following days i've got off work ^^