Open zumpchke opened 5 years ago
Hey Vanush, sorry about the wait there! So once you've got a font file (like OpenSans-Regular.msdf.bin
), you load that as an ArrayBuffer and pass it to GPUText.parse()
. This will give you a GPUTextFont
object.
A GPUTextFont
object is simply the character textures as HTMLImageElement
s along with a map that describes the location of each character in the map (and kerning information). You should create a GPU texture from the images
Then, when you want to render a string of characters, you first need to layout the characters, for example, in the string hello\nworld
, we get a sequence that says character h at position (0,0), character e at position (0.6, 0) and so on, handling kerning, newlines, space characters (and in theory line wrapping). To do this call GPUText.layout( gpuTextFont )
and this gives us a GlyphLayout
object
Now we have the text laid out abstractly, we want to generate something we can pass to the GPU. We generate a mesh, where each character has it's own quad and uvs. The character quads are laid out to match the sequence from layout()
and the uvs correspond to the character location in the texture map. To generate this run GPUText.generateVertexData( glyphLayout )
. The result is a single buffer containing both positions and uvs and layout information to pass to OpenGL that describes how the data is laid out. But generally it's a Float32Array, where each quad vertex has the format p.x, p.y, uv.x, uv.y, uv.z where uv.z is a scale factor.
To render you can use gputext-webgl.js
or copy the shader from there and implement in your own engine
https://github.com/VALIS-software/GPUText/blob/master/example/gputext-webgl.js#L23
Here's a more advanced implementation used in production https://github.com/VALIS-software/Engine/blob/master/src/ui/Text.ts
The layout part of the code is the least complete – laying out text is a can of worms so I've only provided a minimal implementation (just plain RTL with newlines). You might want to use something like harfbuzz if you need to handle other writing systems or word wrapping
@haxiomic How is the OpenSans-Regular.msdf.bin file generated?
Hey @zoldello, that's generated via the command line utility included with this repo like this:
./cli.js source-fonts/OpenSans/OpenSans-Regular.ttf --binary true
This command relies on another tool called msdfgen, if you're on macos the above command should work out of the box because I've included a prebuilt copy of msdfgen, however if you're on windows or linux you'll need to build this (or download prebuilts from here https://github.com/Chlumsky/msdfgen/releases/tag/v1.8) before running the above command
Place msdfgen.exe into this directory https://github.com/VALIS-software/GPUText/tree/master/generate/prebuilt
@haxiomic Does this exception make sense to your (running on mac): (base) saccharo:GPUText phil$ ./cli.js '../../../../Downloads/Mada-Regular_2.ttf' ./ --binary true
Error: ENOENT: no such file or directory, open 'charsets/ascii.txt'
Usage:
_
(base) saccharo:GPUText phil$
Ahh sorry it’s a while since I last ran this - it’s looking for a character set file (which is just a text file containing all the character you want to support)
This file is contained inside generate/charsets, along with some others to choose from
If you add --charset generate/charsets/ascii.txt
it should now work
I've updated the tool so it now uses ASCII by default and doesn't look for this text file (d0f73831247107a17171c8bbaa7c63a116f592d9)
I'm new to GPU text. Can you briefly describe how from a given character, the coordinates of the texels are passed to the shader to render?