Performant and quality 2D text drawing routines
tracked
Send Starlight
Note: This issue was previously accepted on the JIRA as BUG-231731 in 2022. Resubmitting it to the Canny because I think the idea has been lost in the move.
The feature requested is a high performing set of functions that can draw text onto prim surfaces. With multi-line support via \n, measured font sizes, batched draws, and baked font styles compiled into the viewer engine. Restrict this feature to face 0 of the LINK_ROOT prim in an object. A maximum arbitrary number of "screens" could be allowed per region. The maximum limit of llInitDrawString calls per region could be set to for example 256. Attachments would not contribute towards this limit.
Styles baked into the viewer originating from ttf:
integer FONT_STYLE_DEFAULT = 0; // e.g. arial
integer FONT_STYLE_ARIAL = 0;
integer FONT_STYLE_CANDYSCRIPT = 1;
integer FONT_STYLE_SHELLEYALLEGRO = 2;
integer FONT_STYLE_BAUB = 3;
LSL prototypes:
llInitDrawString(integer fontstyle)
Initializes the text context. If this is called again with the same style it should silently return. If called with a different style then change the style. In C++ call initialize the opengltext to delete the previous glyphInfo. If the GLSL program is already linked it is reused.
parameters:
fontstyle: Uses an integer of FONT_* constants that reference baked fonts
llBeginDrawString()
Begins drawing.
float llMeasureString(string text)
Measures the size of the string.
parameters:
text: The text to draw
return value: The measured size.
llDrawString(x, y, text, color)
Draws the string at the position and color.
parameters:
x: x position
y: y position
text: the text string
color: the color
llEndDrawString()
Swaps the buffer onto the face of the prim.
Note: llBeginDrawString just sets an integer in the C++ code to 0.
Example SL script:
drawMyStrings()
{
vector pos1 = <0, 0, 0>;
vector pos2 = <0, 30, 0>;
vector pos3 = <0, 60, 0>;
vector color1 = <1,0,0>;
vector color2 = <1,1,0>;
vector color3 = <0,1,0>;
string text1 = "Hello World!";
string text2 = "It worked.";
string text3 = "This is a\nmultiline string.";
vector sz1 = llMeasureString(text1);
vector sz2 = llMeasureString(text2);
vector sz3 = llMeasureString(text3);
llBeginDrawString();
// This draws "Hello World!" on the first line.
llDrawString(pos1.x - sz1.x * 0.5, pos1.y - sz1.y, text1, color1);
// This draws "It worked." on the next line.
llDrawString(pos2.x - sz2.x * 0.5, pos2.y - sz2.y, text2, color2);
// This draws "This is a" on the third line and "multiline string." on the fourth.
llDrawString(pos3.x - sz3.x * 0.5, pos3.y - sz3.y, text3, color3);
llEndDrawString();
}
default
{
state_entry()
{
llInitDrawString(FONT_STYLE_DEFAULT);
drawMyStrings();
}
}
The OpenGL C++ implementation to place in the viewer code to support this functionality is on github. A patch exists for gltext to for baking. In the viewer these can be looked up with FONT_* constants. The init of the ogl context per font for the text should be instanced once per object using llInitDrawString to be used for multiple scripts and prims without reinitialization. This is destroyed when the viewer releases the object.
There is a bakeFonts.exe for turning ttf fonts into texture atlases to ship with the viewer to bake the fonts and can be produced as .bin and .tga files with offset info. Or, baked into font_xx.h and font_xx_bitmap.h files that can be compiled. This solution does not require the freetype library.
Log In
Send Starlight
Note things like italic or bold etc could be extra constant definitions for a 2nd parameter to llInitDrawString, e.g.:
FONT_MODIFIER_BOLD
FONT_MODIFIER_ITALIC
FONT_MODIFIER_STRIKETHROUGH
FONT_MODIFIER_UNDERLINE
Which could be bitwise combined.
SL Feedback
Hello, and thank you for your detailed feature request regarding performant and quality 2D text drawing routines. We appreciate the effort you put into outlining the specifics and potential benefits of this feature. This issue was previously brought up and accepted on the JIRA as BUG-231731 in 2022. We are merging your comments to ensure it remains on our radar. While we cannot provide an estimate on when this might be implemented, please keep an eye on future updates. Your input is invaluable, and we encourage you to continue sharing your ideas to help improve Second Life. Thank you!
Send Starlight
SL Feedback Thank you! It's time for drawing text onto prims!
Jamesp1989 Resident
Send Starlight hey send james here from the humblebrag server. They are currently looking at some kinda svg support which would cover some of what your looking for https://feedback.secondlife.com/feature-requests/p/svg-canvas-a-way-to-generate-dynamics-graphics-on-prim-faces-without-moap
Send Starlight
Jamesp1989 Resident That will waste a whole lot of RAM compared to my idea. SVG support would be cool but I still think my text draw idea has merit.
There is also:
But, that uses a lot of double-wide byte strings for parameters, so is more wasteful of RAM than my suggestion here which only uses a few floats / vectors, a constant integer for style and one string for the text itself.
Also, my version allows the batching of draw calls, with the final flip caused by llEndDrawString which will be more performant and reduce flicker and draw calls. Which if you look at the C++ code for implementing GL text is how the underlying native code is designed to also work.
And, we're more likely to get a simple text rendering function from LL sooner than a full SVG implementation. And, it's easier for them to test and less likely to have serious security issues and abuse bugs that they have to keep an eye on.
SL Feedback
tracked