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
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.