Some questions about text rendering

Started by .fetox, April 07, 2018, 12:57:04

Previous topic - Next topic

.fetox

Hi all,

first of all I am currently in the process of returning to OpenGL from like 15y ago, where I did some stuff in C++ until the old nVidia Cg shader technology and way before the gl 3.0/3.1 cleanups, so forgive me if I still haven't everything fully sorted :) But now for my questions:

I figured that theres no official way of drawing text in LWJGL, which I find kinda strange on a lib that otherwise covers topics like controller support etc.. I mean.. Its 2018 and I feel oddly set back to a problem that was an issue over a decade ago until FTGL solved it in a wonderful way after my own texture filled with chars stoneage solution. Now what worth is a modern gameing lib without an easy way to use proper unicode ttf font rendering? I know that LWJGL is meant to be low level, but such a functionality is pretty much core functionality for any application.. However, I found that there is some stuff under the hood at least, like the stb wrapper and the TruetypeOversample demo using it. Also there seems to be some FTGL port by warrenfalk on github, but this seems a bit abandoned and also still making use of AWT which I feel a bit akward about in 2018 as well.

So what I tried is misusing the TruetypeOversample source and just throw it into my codebase figuring that it doesn't do anything likely because it is using legacy function while I am doing VAO/VBO/GLSL stuff, but then I got to dig into why it even runs at all on a 4.6 context?? Shouldn't it be impossible to even call legacy functions on a 4.6 context and even if.. shouldn't they at least not work. Seems like the TruetypeOversampling demo is running just fine, checked every flag I could on gl itself and aditionaly the major/minor on glfwGetWindowAttrib() and everything indicated I am running on 4.6. And if there is some interoperability still.. Why doesn't it anymore if I try to use it in my code (I basically made draw_init() and draw_world() in it public and removed the glClear in init, it runs but doesn't show anything).

However, before I start removing legacy calls from it and replace them with shaders and VAO/VBO stuff I wanna make sure that I am not completely misinterpretings something here, or if there is another solution and how this strange behaviour can be explained.

Also I wanna ask if the community isn't in need of some LWJGL core text output functionality and if we shouldn't start on something then (yes, I'm willing to contribute, when people point me into the right direction)?

So much for now, once again excuse me if I overlooked some obvious detail :)

.fetox

Update:

A call to glUseProgram() with 0 as the program parameter fixes it for me and I actually get proper text output on top of my modern shader based renderings. This is however not fitting the OpenGL 4 spec if I read that correctly:

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgram.xhtml

Quote:
"If program is zero, then the current rendering state refers to an invalid program object and the results of shader execution are undefined."

So this call seems to miraculously set back the pipe to some kind of standard shader that resembles the fixed-function one?

KaiHH

The reason why the TruetypeOversample demo works when being put into your own modern OpenGL code is that your driver is likely implementing the OpenGL compatibility profile and you likely did not request a core-only OpenGL context with the GLFW window flag `glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)`.
Just asking for a certain OpenGL version using the GLFW_CONTEXT_VERSION_MAJOR and GLFW_CONTEXT_VERSION_MINOR is not doing anything on some drivers like Nvidia. The driver itself supports everything in order to increase code compatibility.
Only in OpenGL 4.6 Core Profile it is illegal to issue a draw command without a VAO and a shader program being current.
Other drivers behave differently, e.g. to my knowledge only Nvidia and AMD support the compatibility profile and Intel does not. So when you ask for 4.6 or 3.2 without saying you want the core profile, may give you a 2.1 or 3.0 context. This is also the behaviour you'll get on Mac OS. When not asking for a core profile explicitly, you'll get a pre-OpenGL-3.2-era context.
It's pretty difficult to know exactly what you'll get in every situation.
The best you can do is to be explicit about wanting a core profile context. If the driver supports that OpenGL version you're asking for, then you'll definitely get that. But beware that very few cards actually support OpenGL 4.6 and you will have no luck on Mac OS (regardless of the graphics card).

.fetox

Ah, ok, that makes sense. Think the main reason I was confused is that I thought I read somewhere that compatibilty contexts were removed with OpenGL 3.1 or 3.2. And yeah, I did not even request a particular context version, I just read out the values the driver and window gave me from what they created with no specific demand. I tried to even read out the compatibilty bit in GL_CONTEXT_PROFILE_MASK, but this only returns 0:

System.out.println("OpenGL version: " + glGetString(GL_VERSION));
    System.out.println("OpenGL renderer: " + glGetString(GL_RENDERER));
    System.out.println("OpenGL shading language version: " + glGetString(GL_SHADING_LANGUAGE_VERSIONââ,¬â€¹));
    int[] context_profile = new int[1];
    glGetIntegerv(GL_CONTEXT_PROFILE_MASK, context_profile);
    if(context_profile[0] == GL_CONTEXT_CORE_PROFILE_BIT)
    {
      System.out.println("GL_CONTEXT_PROFILE_MASK: GL_CONTEXT_CORE_PROFILE_BIT ");
    }
    if(context_profile[0] == GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
    {
      System.out.println("GL_CONTEXT_PROFILE_MASK: GL_CONTEXT_COMPATIBILITY_PROFILE_BIT");
    }
    System.out.println("GL_CONTEXT_PROFILE_MASK: " + context_profile[0]);

    int window_major_version = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
    int window_minor_version = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);

    System.out.println("Window context version: " + window_major_version + "." + window_minor_version);


gives me:
OpenGL version: 4.6.0 NVIDIA 391.01
OpenGL renderer: GeForce GTX 1080 Ti/PCIe/SSE2
OpenGL shading language version: 4.60 NVIDIA
GL_CONTEXT_PROFILE_MASK: 0
Window context version: 4.6

spasi

On font rendering, not much progress has been made in the past 15 years. It's still mostly glyphs cached in textures.

Quick review of available options: Font Rendering is Getting Interesting
Current state-of-the-art solution: Slug Library (commercial)

.fetox

Quote from: spasi on April 07, 2018, 15:47:51
On font rendering, not much progress has been made in the past 15 years. It's still mostly glyphs cached in textures.

Nothing against glyphs cached in textures, it's more like I feel that LWJGL needs some kind of default implementation (of whatever techique) to add some simple function of print text at coordinate. As of yet even the slightest I-just-wanna-quickly-spit-out-some-debugging-values end up in you having to bother implementing some text out function first, which makes LWJGL look kinda pointless in a second glance for alot of people, which is a shame, cause it is a fine lib besides it lacking a very basic and necessary to 99% of all projects functionality. The tools are there obviously with stb support, now we just need something "official" being able to handle legacy contexts as well as modern. I'll see that I get a modified version of TruetypeOversampled running with VAO/Shader support in the next days that might be developed into something that can be added to the core. So input is welcome :)

spasi

Quote from: .fetox on April 07, 2018, 17:15:42I feel that LWJGL needs some kind of default implementation (of whatever techique) ... which makes LWJGL look kinda pointless in a second glance for alot of people ... now we just need something "official"

That's all by design. LWJGL provides bindings to native libraries, it does nothing else. There are no plans to add high-level functionality on top. There are plenty of libraries/frameworks out there that wrap LWJGL and expose useful functionality.

The best LWJGL can do is include richer demos and code samples. These are completely unsupported, but you're free to learn from them or copy the code to get started quickly. This is exactly the purpose of the stb demos.

(note: We're not allergic to high-level functionality, there's just not enough manpower to do anything else. We're already behind schedule as it is.)

Quote from: .fetox on April 07, 2018, 17:15:42the slightest I-just-wanna-quickly-spit-out-some-debugging-values end up in you having to bother implementing some text out function first

Have you seen the stb_easy_font demo? You can render text with literally one line of code, you don't even need textures or shaders. It doesn't get simpler than that.