[SOLVED] LWJGL3 + Slick: How to properly render text

Started by _gjkf_, July 06, 2015, 15:26:17

Previous topic - Next topic

_gjkf_

Hello everyone!

I'm really new to the OpenGL/LWJGL world therefore my problem might be really easy to solve. My problem here is when I try to render some text onto the screen. I've read many different posts in many different places on how this can be done. I'm currently using the Slick2D library to try achieving it. I'm using the UnicodeFont class. Let me show you some relevant code:

UnicodeFont font = new UnicodeFont(new Font("Times New Roman", Font.PLAIN, 24));
font.addAsciiGlyphs();
try{
    font.loadGlyphs();
}catch(SlickException e){
    e.printStackTrace();
}
font.drawString(100, 100, "test");


I do this after the setup:
public void setup(){
        int glfwResult = glfwInit();
        if(glfwResult == GL_FALSE){ //In case the initialization fails
            throw new IllegalStateException("GLFW Initialization failed");
        }

        glfwDefaultWindowHints(); // Loads GLFW's default window settings
        glfwWindowHint(GLFW_VISIBLE, GL_TRUE); // Sets window to be visible

        Constants.windowID = glfwCreateWindow(Constants.width, Constants.height, "Fractal", MemoryUtil.NULL, MemoryUtil.NULL);

        if(Constants.windowID == MemoryUtil.NULL){ //In case the initialization fails
            throw new IllegalStateException("Window creation failed");
        }

        glfwMakeContextCurrent(Constants.windowID); //Needs to be here
        glfwSwapInterval(1); //Caps the fps to 60 with VSync
        glfwShowWindow(Constants.windowID);

        GLContext.createFromCurrent(); //Binds the OpenGL context to the current thread, the GLFW one

        glEnable(GL_TEXTURE_2D);
        glShadeModel(GL_SMOOTH);
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_LIGHTING);

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClearDepth(1);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        MouseInput.registerMouseInput(); //Registering the mouse inputs

        glClearColor(0F, 0F, 0F, 0F);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        {//For normal use
            glViewport(0, 0, Constants.width,Constants. height);
            glMatrixMode(GL_MODELVIEW);

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, Constants.width, Constants.height, 0, 1, - 1);
            glMatrixMode(GL_MODELVIEW);
        }

        screen = GUIs.mainScreen;
        screen.render();

        UnicodeFont font = new UnicodeFont(new Font("Times New Roman", Font.PLAIN, 24));
        font.addAsciiGlyphs();
        try{
            font.loadGlyphs();
        }catch(SlickException e){
            e.printStackTrace();
        }
        font.drawString(0, 0, "test");

        lastFPS = getTime(); //Sets for the first time the FPS
}


My problem here is that the application becomes unresponsive to all inputs but mouse ones. The FPS are not shown anymore in the console. The game loop looks like dead even before it actually started.

If you need any additional code I'll be more than happy to give it to you. Last additional note, I'm on MacOSX

I hope that someone can help me. I've been stuck on this for 5 days now.

quew8

OK first question, where is your actual game loop, and what is this stuff doing?

Quote
screen = GUIs.mainScreen;
screen.render();

Second question, is it the font rendering that is causing this? If you remove all the font rendering stuff does it work as expected? And what is expected?

_gjkf_

1) Here's the game loop

public void loop(){
        while(glfwWindowShouldClose(Constants.windowID) == GL_FALSE){ //As long as the window should not close, keep updating it
            glClear(GL_COLOR_BUFFER_BIT); //Clear the contents of the window
            draw();
            updateFPS(); //Updating the fps count
            KeyboardInput.registerKeyboardInput(); //Just a class checking for each button press
            glfwPollEvents(); //Catches all the mouse/keyboard events, makes the application actually responsive
        }
}

public void draw(){

        screen.update();

        // Fractals.drawJulia(new ComplexNumber(-0.8, 0.156), 0.01, 200000, 100, new double[]{0.5, 0.5});
        Fractals.drawMandelbrot(0.01, 1000, 100, new double[]{0.75, 0.75});

        glfwSwapBuffers(Constants.windowID);
}


That thing is where I first render the GUI. Currently does almost nothing since I'm trying to make buttons and for them I need text.

This would update the current screen, again, it's blank for now.
screen.update();


This is just for rendering a mandelbrot set. Works fine if all alone.
Fractals.drawMandelbrot(0.01, 1000, 100, new double[]{0.75, 0.75});


2) After some tests, I found out that the problem come in this line
UnicodeFont font = new UnicodeFont(new Font("Times New Roman", Font.PLAIN, 24));

and it seems like the instantiation of a new Font object blocks the application.

If I remove everything from the font renderer works fine, renders the fractal and all the inputs work (mouse and keyboard) (Actually the mouse one crashes the app whenever I draw any fractal. Not really sure why)

What I'm expecting to see is some text on the screen while the application is still responsive.

SHC

Wait are you on Mac OS X? Then you should be setting the headless property of the AWT to prevent blocking of the main thread.

System.setProperty("java.awt.headless", "true");


Set this property in the main method before you start your game and it should be fine.

_gjkf_

Adding that line kinda worked. Now I' getting a crash.

Connected to the target VM, address: '127.0.0.1:51167', transport: 'socket'
2015-07-07 11:04:23.186 java[578:707] [JRSAppKitAWT markAppIsDaemon]: Process manager already initialized: can't fully enable headless mode.
Exception in thread "main" java.lang.NoSuchMethodError: org.lwjgl.opengl.GL11.glGetInteger(ILjava/nio/IntBuffer;)V
	at org.newdawn.slick.opengl.renderer.ImmediateModeOGLRenderer.glGetInteger(ImmediateModeOGLRenderer.java:194)
	at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:428)
	at org.newdawn.slick.opengl.InternalTextureLoader.createTexture(InternalTextureLoader.java:374)
	at org.newdawn.slick.Image.<init>(Image.java:237)
	at org.newdawn.slick.Image.<init>(Image.java:221)
	at org.newdawn.slick.font.GlyphPage.<init>(GlyphPage.java:105)
	at org.newdawn.slick.UnicodeFont.loadGlyphs(UnicodeFont.java:374)
	at org.newdawn.slick.UnicodeFont.loadGlyphs(UnicodeFont.java:325)
	at com.gjkf.fractal.game.Game.setup(Game.java:106)
	at com.gjkf.fractal.game.Game.<init>(Game.java:45)
	at com.gjkf.fractal.Fractal.main(Fractal.java:34)
Disconnected from the target VM, address: '127.0.0.1:51167', transport: 'socket'

Process finished with exit code 1


The first line has appeared only after I put what SHC suggested.

I took a look at the class ImmediateModeOGLRenderer and I get compile errors. I've downloaded the slick jar from here and seems like it's outdated. So what options do I have? Using the TrueTypeFont instead of the Unicode one? I tried and I get another crash caused by the same class.

So now what can I do?

kappa

Slick is written for LWJGL2 and isn't compatible with LWJGL3. A good option is to use LWJGL3's builtin STB binding to load and display fonts. There are examples of STB usage in the LWJGL3 repo.

_gjkf_

I'll take a look at it. Look rather confusing though. Thanks.

EDIT: got it! Thank you so much!