簡體   English   中英

如何使用GLSL在現代OpenGL中呈現文本

[英]How to render text in modern OpenGL with GLSL

我想通過使用現代OpenGL(使用VBO和着色器渲染)在LWJGL中渲染文本,但我不知道如何做到這一點。

這是一種方法:

  • 創建一個包含所有字符的紋理,並按特定大小進行柵格化。
  • 對於每個字符,存儲包含該字符的紋理的補丁的位置

class CharCoords {
    public int x, y, width, height;
}
  • 將具有頂點(0,0), (0,1), (1,0), (1,1)的2D方形幾何上傳到GPU
  • 頂點着色器可能如下所示

#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();
}
  • 注意:要設置文本的比例和位置,請相應地修改模型矩陣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM