opengl - 如何使用GLSL在现代OpenGL中渲染文本

标签 opengl fonts glsl shader lwjgl

我想通过使用现代OpenGL(使用VBO和着色器渲染)在LWJGL中渲染文本,但是我不知道该怎么做。

最佳答案

这是一种方法:

  • 创建包含所有字符的纹理,并以一定大小对其进行栅格化。
  • 对于每个字符,存储包含字符
  • 的纹理补丁的位置


    class CharCoords {
        public int x, y, width, height;
    }
    
  • 将带有顶点的2D正方形几何上传到GPU。(0,0), (0,1), (1,0), (1,1)
  • 顶点着色器可能如下所示


  • #version 120
    
    uniform mat4 PVMmat;        // The projection-view-model matrix
    uniform vec4 charCoords;    // The CharCoord struct for the character you are rendering, {x, y, w, h}
    uniform float texSize;      // The size of the texture which contains the rasterized characters (assuming it is square)
    uniform vec2 offset;        // The offset at which to paint, w.r.t the first character
    
    attribute vec2 vertex;
    
    varying vec2 tc;
    
    void main(){
        // Transform from absolute texture coordinates to normalized texture coordinates
        // This works because the rectangle spans [0,1] x [0,1]
        // Depending on where the origin lies in your texture (i.e. topleft or bottom left corner), you need to replace "1. - vertex.y" with just "vertex.y"
        tc = (charCoords.xy + charCoords.zw * vec2(vertex.x, 1. - vertex.y)) / texSize;
    
        // Map the vertices of the unit square to a rectangle with correct aspect ratio and positioned at the correct offset
        float x = (charCoords[2] * vertex.x + offset.x) / charCoords[3];
        float y = vertex.y + offset.y / charCoords[3];
    
        // Apply the model, view and projection transformations
        gl_Position = PVMmat * vec4(x, y, 0., 1.);
    }
    
  • 片段着色器很简单:


  • #version 120
    
    uniform vec4 color;
    uniform sampler2D tex;
    
    varying vec2 tc;
    
    void main() {
        gl_FragColor = color * texture2D(tex, tc);
    }
    
  • 然后,您的绘图函数可能如下所示(注意:代码正在使用带有一些便捷方法的着色器类,但是思路应该很清楚):


  • public void drawString(Matrix4f PVMmat, String text, Color color, HAlign halign, VAlign valign) {
        Vector2f offset = new Vector2f();
    
        // Font alignment
        if(halign == HAlign.Center){
            offset.x = -(int) (0.5f * getWidth(text));
        }else if(halign == HAlign.Right){
            offset.x = -getWidth(text);
        }
        if(valign == VAlign.Middle){
            offset.y = -(int) (0.5f * getHeight());
        }else if(valign == VAlign.Top){
            offset.y = -getHeight();
        }
    
        m_shader.bind();        
        m_shader.setAttributeBuffer("vertex", m_vertexBuffer, 2);
        m_shader.setUniformMatrix("PVMmat", PVMmat);
        m_shader.setUniformVector("color", color);
        m_shader.setUniformScalar("texSize", (float)m_textureSize);
        m_shader.setTexture("tex", m_fontTexture, GL11.GL_TEXTURE_2D);
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, m_model.getIndexBuffer());
        for(int i = 0; i < text.length(); ++i) {
            CharCoords coo = m_charMap.get(text.charAt(i));
            m_shader.setUniformVector("charCoords", new Vector4f(coo.x, coo.y, coo.width, coo.height));
            m_shader.setUniformVector("offset", offset);
            GL11.glDrawElements(GL11.GL_TRIANGLES, m_indexCount, GL11.GL_UNSIGNED_INT, 0);
            offset.x += coo.width;
        }
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        m_shader.unbind();
    }
    

    函数getHeigthgetWidth是:

    public int getWidth(String text) {
        int totalwidth = 0;
        for (int i = 0; i < text.length(); i++) {
            CharCoords coo = m_charMap.get(text.charAt(i));
            totalwidth += coo.width;
        }
        return totalwidth;
    }
    
    public int getHeight() {
        return m_fontMetrics.getHeight();
    }
    
  • 注意:要设置文本的比例和位置,请相应地修改模型矩阵。
  • 关于opengl - 如何使用GLSL在现代OpenGL中渲染文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22080881/

    相关文章:

    c++ - 如何将 "camera"放入 OpenGL 的立方体中

    css - 无法覆盖字体大小 :100% & font-inherit property in another CSS file

    opengl - 是否有用于OpenGL阴影语言的 Lint 工具?

    fonts - 如何使用绝对路径更改matplotlib中的字体?

    ios - 在 Swift 中更改导航栏中的字体

    python - 片段着色器 : get distance from fragment to bezier curve

    c++ - glsl 中的显式或隐式 vec4

    c++ - glGetActiveUniformName 的异常行为

    opengl - 为什么具有 Opengl 3.0 上下文的 SFML 会绘制两次?

    c++ - glsl - 光线行进在片段着色器中不起作用