You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的深度测试逻辑:

  1. 在init方法中创建了VAO和VBO,但未给这些缓冲区填充任何有效顶点数据,也没有实际使用它们进行绘制。
  2. 启用的顶点属性数组(glEnableVertexAttribArray(0)和1)会让OpenGL管线尝试读取未初始化的缓冲区垃圾数据,这些数据被写入深度缓冲区后留下异常深度值。
  3. TextRenderer默认依赖OpenGL的深度测试机制,绘制英文字符"S"时,其渲染的深度值与深度缓冲区中的垃圾值冲突,导致字符被深度测试剔除,无法显示。
  4. 俄文字符"Й"的字形渲染区域刚好避开了深度缓冲区中异常值的影响范围,因此能正常显示。

解决方案

有两种简单的修复方式:

方案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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:52:37