[Solved][JOGL] Rendering text

Hello everyone,

As many JOGL developers, I’m facing troubles to easily render text over a 3D scene (the TextRenderer class didn’t provide me suitable results as it always ended with a “not a GL2 context” error). Then I decided to create my own class that could do the job and after a few days, I managed to render text with the following steps :
[] creation of a 2D graphics structure,
[
] rendering my text inside a buffered image using this 2D graphics structure,
[] generating some texture data from the buffered image,
[
] rendering a 2D square in the foreground where the texture data is applyied.

The code that implements those steps is available below :wink:

I’m starting to get very interesting results but the fact is that my 2D square always have a black background. I can solve my problem inside the vertex shader, re-computing the alpha value with 100% black => 0% alpha, but it’s not a very nice solution to me. Anyway, here’s the vertex shader code if anybody’s interested :


void main() {
    vec4 textureColor = texture(defaultTexture, UvCoordinates);
    outColor.a = 1. - (textureColor.r + textureColor.g + textureColor.b) / 3.;
    outColor.rgb = vec3(1, 1, 1) - textureColor.rgb;
}

Considering the following code that implements text rendering into texture data, does someone see why my texture data always have a black background, please ?


public void drawFont(GL3 gl, float x, float y, String text, Color color, int size) {
    // Generating the font
    BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
    Graphics2D graphics = bufferedImage.createGraphics();
    java.awt.Font drawingFont = font.deriveFont(java.awt.Font.PLAIN, size);
    graphics.setFont(drawingFont);

    // Computing the dimensions of the text depending on the font and on the text to draw
    FontMetrics fontMetrics = graphics.getFontMetrics();
    int width = fontMetrics.stringWidth(text);
    int height = fontMetrics.getHeight();
    float screenRelativeWidth = 2f * width / (float) DisplayManager.getDrawingSurfaceWidth();
    float screenRelativeHeight = 2f * height / (float) DisplayManager.getDrawingSurfaceHeight();
    graphics.dispose();

    // Buffering the rendered font into a buffered image
    bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    graphics = bufferedImage.createGraphics();
    graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
            RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);

    graphics.setFont(drawingFont);
    fontMetrics = graphics.getFontMetrics();
    graphics.setColor(color);
    graphics.drawString(text, 0, fontMetrics.getAscent());
    graphics.dispose();

    // The following lines generates a file where the text is properly rendered, with right alpha
    try {
        File outputfile = new File("Font rendering.png");
        ImageIO.write(bufferedImage, "png", outputfile);
    }
    catch (IOException e) {
        logger.error("Could not save the generated buffered image to draw the font :", e);
    }

    // Converting the buffered image into a texture
    AWTTextureData textureData = new AWTTextureData(gl.getGLProfile(), GL.GL_RGBA, 0, false, bufferedImage);
    Texture texture = new Texture(gl, textureData);

    // Activating the texture containing the text
    FxManager.useShader(gl, fontMaterial.shading);
    if (FxManager.defaultTextureHandler != -1 && texture != null) {
        gl.glBindTexture(GL.GL_TEXTURE_2D, setTextureHandler(gl));
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, texture.getInternalFormat(), texture.getWidth(), texture.getHeight(),
                0, texture.getPixelFormat(), texture.getPixelType(), texture.getBuffer());
        gl.glGenerateMipmap(GL.GL_TEXTURE_2D);
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
        gl.glActiveTexture(GL.GL_TEXTURE0);
        gl.glBindTexture(GL.GL_TEXTURE_2D, textureHandler);
    }

    // Rendering the square on which the font texture is applyied
    bufferRenderingSquareData(gl, x, y, screenRelativeWidth, screenRelativeHeight);
    gl.glDrawElements(GL3.GL_TRIANGLES, 6, GL3.GL_UNSIGNED_INT, 0);
    gl.glDisableVertexAttribArray(0);
    gl.glBindVertexArray(0);

    // Once the text is rendered, disabling the material
    MaterialManager.disableMaterial(gl);

The problem seems to occur when I convert the buffered image into a texture (line 40 above). I tried to have a look inside the AWTTextureData constructor but nothing seems to be wrong in the way I declare it. Of course, if anymore information is needed, feel free to ask.

Thanks for your help.