OpenGL TextRenderer无法显示英文字母问题排查求助
问题:OpenGL TextRenderer显示英文字符失败,俄文字符却正常的原因?
以下是最小可复现代码:
import com.jogamp.opengl.GL4; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.awt.GLCanvas; import com.jogamp.opengl.util.awt.TextRenderer; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import static com.jogamp.opengl.GL4.*; public class Test extends Frame implements GLEventListener { private static int[] vao = new int[1]; private static int[] vbo = new int[4]; private static GLCanvas canvas; private static GL4 gl; private static int WIDTH = 750, HEIGHT = 750; private TextRenderer textRenderer; public Test() { canvas = new GLCanvas(); canvas.addGLEventListener(this); this.add(canvas); this.setSize(WIDTH, HEIGHT); this.setVisible(true); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); } public static void main(String[] args) { new Test(); } @Override public void init(GLAutoDrawable drawable) { gl = (GL4) drawable.getGL(); gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl.glGenVertexArrays(vao.length, vao, 0); gl.glBindVertexArray(vao[0]); gl.glGenBuffers(vbo.length, vbo, 0); gl.glEnableVertexAttribArray(0); gl.glEnableVertexAttribArray(1); textRenderer = new TextRenderer(new Font("Arial", Font.BOLD, 20)); } @Override public void display(GLAutoDrawable drawable) { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); String letter = "Й"; // Й works, S doesn't textRenderer.beginRendering(WIDTH, HEIGHT); textRenderer.setColor(Color.WHITE); textRenderer.draw(letter, WIDTH / 2, HEIGHT / 2); textRenderer.endRendering(); } @Override public void dispose(GLAutoDrawable drawable) { textRenderer.dispose(); } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} }
现象:将字符设置为"S"时仅显示黑色背景,无法显示英文字母;设置为俄文字母"Й"时可正常显示白色字母。
原因分析
问题核心是无效的VAO/VBO初始化代码干扰了TextRenderer的深度测试逻辑:
- 在
init方法中创建了VAO和VBO,但未给这些缓冲区填充任何有效顶点数据,也没有实际使用它们进行绘制。 - 启用的顶点属性数组(
glEnableVertexAttribArray(0)和1)会让OpenGL管线尝试读取未初始化的缓冲区垃圾数据,这些数据被写入深度缓冲区后留下异常深度值。 - TextRenderer默认依赖OpenGL的深度测试机制,绘制英文字符"S"时,其渲染的深度值与深度缓冲区中的垃圾值冲突,导致字符被深度测试剔除,无法显示。
- 俄文字符"Й"的字形渲染区域刚好避开了深度缓冲区中异常值的影响范围,因此能正常显示。
解决方案
有两种简单的修复方式:
方案1:移除无用的VAO/VBO代码
既然未用到这些顶点缓冲区,直接删除init中相关代码即可:
@Override public void init(GLAutoDrawable drawable) { gl = (GL4) drawable.getGL(); gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 移除所有未使用的VAO/VBO初始化代码 textRenderer = new TextRenderer(new Font("Arial", Font.BOLD, 20)); }
方案2:渲染文本时禁用深度测试
如果后续需要保留VAO/VBO用于其他绘制,可以在渲染文本前临时禁用深度测试:
@Override public void display(GLAutoDrawable drawable) { gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 临时禁用深度测试,避免TextRenderer被异常深度值遮挡 gl.glDisable(GL_DEPTH_TEST); String letter = "S"; textRenderer.beginRendering(WIDTH, HEIGHT); textRenderer.setColor(Color.WHITE); textRenderer.draw(letter, WIDTH / 2, HEIGHT / 2); textRenderer.endRendering(); // 按需恢复深度测试(如果后续有3D绘制需求) gl.glEnable(GL_DEPTH_TEST); }
内容的提问来源于stack exchange,提问作者parsecer
相关产品推荐
相关产品推荐

