flyx / OpenGLAda

Thick Ada binding for OpenGL and GLFW
flyx.github.io/OpenGLAda/
MIT License
95 stars 13 forks source link

High-Level API for text rendering #99

Closed flyx closed 6 years ago

flyx commented 6 years ago

Using the FTGL binding is not flexible enough and should be deprecated. Instead, we should implement an own high-level text rendering API based on the new FreeType binding.

I started implementing this and got it to a level where text is rendered onto a texture. However, it is not completely working and I hope @rogermc2 can be of some assistance since my OpenGL is a bit rusty.

Current test program can be compiled with opengl-freetype-test.gpr. It depends on Strings_Edit for parsing UTF-8 input (so that we can render arbitrary unicode characters). TODOs:

I look forward to your comments, @rogermc2 .

rogermc2 commented 6 years ago

The source code looks good to me, pending getting my copy of the project working. The only thing that I suggest is putting the vertex and fragment sampler code into their own GLSL files. I much prefer this as it is much neater. I am working in my string_example_extensions branch and have put strings_edit in the src directory with strings_edit.gpr in the top level directory. I made a fresh strings_edit.gpr which places the library into lib hoping to set upeverthing "as normal" However, I can't figure out how to fix the following bind errors. I have checked that other freetype projects build OK. I have had this problem in the past, I think when we were reorganising things, but could eventually fix it. My problem is that I can't remember how I fixed it then. I have checked that there is only one ft.ads on my system.

error: "ft.adb" must be recompiled ("ft.ads" has been modified)
error: "ft-api.ads" must be recompiled ("ft.ads" has been modified)
error: "ft-errors.adb" must be recompiled ("ft.ads" has been modified)
error: "ft-faces.adb" must be recompiled ("ft.ads" has been modified)
error: "ft-glyphs.adb" must be recompiled ("ft.ads" has been modified)
error: "ft-api-glyphs.ads" must be recompiled ("ft.ads" has been modified)
gprbind: invocation of gnatbind failed
gprbuild: unable to bind freetype_test-basic.adb
flyx commented 6 years ago

Execute gprclean on the project (GPS can do it), that usually fixes those errors.

I intentionally put the shaders into the program source because GL.FreeType is a library and I cannot assume anything about the packaging of the resulting program, so I cannot make sure that the shader source files are spread alongside the library, and if so, at which path they can be found.

You can install strings_edit by downloading its source and executing gprinstall which places it in a location where gprbuild can find it automatically.

rogermc2 commented 6 years ago

I have tried gprclean but it didn't solve the problem, but I'll leave that problem until after I get strings_edit properly installed. I started with a fresh copy of strings_edit, then, using the instructions in 'http://www.adacore.com/adaanswers/gems/gem-158-gprinstall/' tried gprbuild -p strings_edit.gpr then

:/Ada_Source/strings_3_2 Roger$gprinstall -p strings_edit.gpr 
Install project Strings_Edit
file strings_edit-integers-superscript.o exists, use -f to overwrite
:/Ada_Source/strings_3_2 Roger$gprinstall -f -p strings_edit.gpr 
Install project Strings_Edit
file /Ada_Source/strings_3_2/strings_edit-text_edit.o does not exist, build may not be complete

If I try gprinstall first, I get:

:/Ada_Source/strings_3_2 Roger$sudo gprinstall -p strings_edit.gpr 
Install project Strings_Edit

Execution terminated by unhandled exception
raised ADA.IO_EXCEPTIONS.NAME_ERROR : /Ada_Source/strings_3_2/strings_edit-float_edit.o: No such file or directory
Load address: 0x104089000
Call stack traceback locations:
0x10443269f 0x10440094e 0x1040c92dd 0x1040db69f 0x10413562c 0x10408b988 0x104458771

My previous method of building worked but, of course, it didn't "place it in a location where gprbuild can find it automatically". Any idea what's wrong?

flyx commented 6 years ago

I have never had any problems with gprinstall, so I don't know what goes wrong here. Does the gprbuild step produce any warnings?

rogermc2 commented 6 years ago

It only seems to do compiles, no warnings or errors:

Ada_Source/strings_3_2 Roger$sudo gprbuild -p strings_edit.gpr 
Password:
Compile
   [Ada]          strings_edit-float_edit.adb
   [Ada]          strings_edit-integers-superscript.ads
-
-
-
   [Ada]          strings_edit-utf8-subscript.adb
   [Ada]          strings_edit-streams-generic_integer.adb
:/Ada_Source/strings_3_2 Roger$
flyx commented 6 years ago

does it compile strings_edit-text_edit.adb, since strings_edit-text_edit.o seems to be missing?

rogermc2 commented 6 years ago

strings_edit-text_edit.adb is not in the gprbuild list of compilations but is definitely in the strings_3_2 directory. It is also in the source file list of strings_edit.gpr.

flyx commented 6 years ago

Then I would try to figure out why it is not part of the compilation, since that is what gnatinstall chokes on later. You could ask on comp.lang.ada since the author of Strings_Edit hangs around there.

rogermc2 commented 6 years ago

I think I've found the solution. I apparently need to use Dmitry's GPS LIBRARY INSTALLER, not gprinstall. This turned out not to be the solution. GPS LIBRARY INSTALLER not needed.

flyx commented 6 years ago

Interesting, I did not need to use that. Anyway, just pushed an update that improves everything. Still some work left to be done.

rogermc2 commented 6 years ago

Also doesn't find the sampler files. I had to provide full path names to get it to work. Obviously not a solution but I couldn't find relative path names that worked. The program then worked displaying the text but then failed with:

Rendered text to texture
Initialized objects
Loaded shaders
Loaded data
objc[43821]: Invalid or prematurely-freed autorelease pool 0x7f995a8060e0.

raised PROGRAM_ERROR : unhandled signal

Code is looking good. I can't see that I can provide much help but will continue to follow your efforts with interest; waiting until I can see how to use it in place of my own texture_management which is working fine on my current project, the interface being:

 procedure Initialize_Font_Data (Font_File : String);
   procedure Render_Text (Render_Program : GL.Objects.Programs.Program;
                          Text   : String; X, Y, Scale : GL.Types.Single;
                          Colour : GL.Types.Colors.Basic_Color;
                          Texture_ID, Projection_Matrix_ID,
                          Colour_ID : GL.Uniforms.Uniform;
                          Projection_Matrix : GL.Types.Singles.Matrix4);
flyx commented 6 years ago

The relative path names I provided work for me on macOS High Sierra when executing the program from within the bin directory. Your error hints to an external cause (it's an Objective-C error message), you could try updating your glfw library. Which GNAT are you using?

rogermc2 commented 6 years ago

The error actually occurs when I quit the program. I just changed to GNAT 2017. Now the error is:


libc++abi.dylib: terminating with uncaught foreign exception

raised PROGRAM_ERROR : unhandled signal
~~
rogermc2 commented 6 years ago

Relative paths work with ../tests/ replaced by tests/

flyx commented 6 years ago

You need to start the executable with bin as working directory to make ../tests/ work. I do it this way because when launching from within GPS, you can select to run from the executable's dir – otherwise, it'll start from the working directory of GPS which could be anywhere. So making it work from the directory where the executable is located seems the sensible way to go.

rogermc2 commented 6 years ago

My 'edit_strings` woes seem to have actually been caused by using an "old" GNAT. Switching to GNAT 2017 is what fixed it.

flyx commented 6 years ago

Good to hear! I still wonder where the error on exit comes from. It works fine for me on both macOS and Windows.

btw, I pushed some renaming and API improvement earlier – the package is now called GL.Text.

rogermc2 commented 6 years ago

I now have it working using ../tests/ and no exit error, at least on one computer but not the other!

flyx commented 6 years ago

Feature-wise, I have the code ready. Only things missing are documentation and information about whether your problems can be solved by improving the implementation.

rogermc2 commented 6 years ago

Its working OK on one of my computers. Except that I get the following build warnings:

warning: "gl-text.adb" has dynamic elaboration checks and with's
warning:   "strings_edit.ads" which has static elaboration checks
warning: "gl-text.adb" has dynamic elaboration checks and with's
warning:   "strings_edit-utf8.ads" which has static elaboration checks

I was getting these warnings on previous versions.

rogermc2 commented 6 years ago

I don't get the build warnings on my other computer but on program termination I get:

libc++abi.dylib: terminating with uncaught foreign exception

raised PROGRAM_ERROR : unhandled signal
[2017-10-28 12:18:47] process exited with status 1, elapsed time: 03.54s

Relative paths work with ../tests/ now works on both computers.

flyx commented 6 years ago

I fixed the warnings (you may need to explicitly clean your project before compiling for it to go away). Maybe it also fixes the error?

If not, can you check whether you have different GLFW or compiler versions on the two machines?

rogermc2 commented 6 years ago

Hasn't fixed the error. Warnings gone. GNAT same on both machines. Yet to check others.

rogermc2 commented 6 years ago

On both machines:

MacBook-Air:OpenGLAda rogermcmurtrie$ brew list glfw
/usr/local/Cellar/glfw/3.2.1/include/GLFW/ (2 files)
/usr/local/Cellar/glfw/3.2.1/lib/libglfw.3.2.dylib
/usr/local/Cellar/glfw/3.2.1/lib/cmake/ (4 files)
/usr/local/Cellar/glfw/3.2.1/lib/pkgconfig/glfw3.pc
/usr/local/Cellar/glfw/3.2.1/lib/ (2 other files)

I've checked XCode on both machines: Version 9.0 Do I need to check something else?

flyx commented 6 years ago

Looks fine. I am currently at a loss about what may be wrong. Need to find a way to inspect this „foreign exception“ that arises. Does the program run correctly apart from that error at termination?

rogermc2 commented 6 years ago

Worked OK a few times then the problem reappeared. Actually, the first time I ran it on the other machine after clean and rebuild, the error occurred but after that ran OK. No other problems. However, the text in the source code is:

"The quick bröwn füx jumpß over the lazy 💩dog."

The displayed text is much better. However, the o in brown is displayed with two dots over the o The o in fox is displayed as u with two dots above. The s in jumps is displayed as the Greek letter beta. dog is preceded by a ?

flyx commented 6 years ago

The text looks scrambled because it is encoded in UTF-8. Sadly, GNAT does a very poor job at supporting UTF-8 as input encoding. The only way I got it to work is to not use the switch -gnatW8 (which activates UTF-8 decoding when parsing) because that re-encodes the String in ANSI. Since GPS does not support editing source files encoded in UTF-8, the text looks broken.

Basically, I replaced some letters with umlauts / other non-ASCII characters to check whether UTF-8 support is working. The string correctly reads

The quick bröwn füx jumpß over the lazy 💩dog.

First time I ever used these emoji things – I basically needed a character which is guaranteed to not exist in the font I loaded, to check whether it gets substituted with ? which is the fallback for such cases. Maybe I should change that emoji to an, um, more neutral one ^^.

Btw, the ß is a german letter with a long history, dating back to a ligature merge in Fraktur writing, see here.

rogermc2 commented 6 years ago

OK. The string is being displayed correctly assuming that the emoji thing should be replaced by a ?. Your reference to ß is interesting, albeit complex!

flyx commented 6 years ago

Good, so I assume there are no further obvious errors.

I decided to do away with opengl_shared.gpr because everything that depends on it also depends on opengl.gpr, so I can place everything in there. I will make sure that example projects that depend on it also get updated.

I may do a new release soon to announce the availability of the new font rendering tools – both the basic FreeType binding and GL.Text.

rogermc2 commented 6 years ago

I'll have a go at using the new font rendering tools in my current project in place of my current text rendering program. Actually, I'll first try reproducing my current text rendering example using GL.Text.

flyx commented 6 years ago

Just found this which looks totally awesome, but I will probably never have time to implement it :(

flyx commented 6 years ago

Docs are online, tell me whether you have problems with using GL.Text. If not, we can close this issue.

rogermc2 commented 6 years ago

Almost got my first use of GL.Text working. GL.Text itself seems OK so can close. By the way, as part of this exercise I have implemented the common directory files as a library libcommon.a and have converted the Examples to use this library. I assume that this is OK?

rogermc2 commented 6 years ago

I have now used GL.Text in my geometric algebra project rendering a display that includes 24 separate text strings. So definitely can close.

rogermc2 commented 6 years ago

Wonderful news!