OpenGL テクスチャを利用して文字を描画する

opengl-textured-font-rendering.png

まずはビットマップフォントの画像を用意する

BitmapFont Generatorというものがあって
たとえばこれcbfg
自分のパソコンにインストールされているフォントから文字が整列してならんだテクスチャを生成してくれます。
cbfg.png
エクスポートしたのがこちら(bitmapやtgaで出力可能)
8行x8列の表になって出てきます。
agencyb.bmp
ここから知恵をしぼってテクスチャ座標を割り出しましょう~
Asciiコードを利用すれば自動的にテクスチャ座標を算出することができます

ソースコード

フルソースコード(Text.cpp,Text.h)

    void InitFonts() {
        //ビットマップフォントを読み込む
        cv::Mat image = cv::imread("agencyb.bmp");
        if (image.empty()) assert(!"OpenCV load image error");
        glGenTextures(1,&mFontTextureId);
        glBindTexture(GL_TEXTURE_2D, mFontTextureId);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0, GL_RGB, GL_UNSIGNED_BYTE, image.data);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
        GLuint vbo;
        glGenBuffers(1, &vbo);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        char target_char = 'x';
        //8行x8列のビットマップフォントなので
        const float glyphnum = 8.0f;
        float u = (target_char % 8) / 8.0f;
        float v = (target_char / 8) / 8.0f;
        float font_size = 0.3f;
        static const GLfloat quad_data[] =
        {
                     0.0, 0.0,
            font_size, 0.0,
            font_size, font_size,
                      0.0, font_size,
            //テクスチャ座標
            0.0f     , 1.0/8.0f ,//割る数値はy方向のビットマップフォントの個数
            1.0/8.0f , 1.0f/8.0f,
            1.0/8.0f , 0.0f,//割る数値はx方向のビットマップフォントの個数
            0.0f     , 0.0f
        };
 
        glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW);
 
        glGenVertexArrays(1, &mFontVao);
        glBindVertexArray(mFontVao);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);//位置
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (const void*)(8 * sizeof(float)));//テクスチャ座標
 
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
 
        glBindBuffer(GL_ARRAY_BUFFER, mFontVao);
 
    }

頂点シェーダ

#version 400
out vec2 vUV;
uniform mat4 uModelViewProj;
uniform vec3 uScale;
uniform vec3 uBeginPosition;
in vec3 inPosition;
in vec2 inUV;
uniform vec2 uUvBegin;
void main () {
    vec3 pos = uScale * inPosition + uBeginPosition;
  gl_Position = uModelViewProj * vec4(pos, 1.0);
  vUV = inUV + uUvBegin;
}

フラグメントシェーダ

#version 400
in vec2 vUV;
out vec4 frag_color;
uniform vec4 uColor;
uniform sampler2D uTex;
void main () {
    float luminance = texture2D(uTex, vUV).r;
    frag_color = vec4(uColor.rgb, luminance);
}

描画関数にて

        //文字を描画する
        glBindVertexArray(mFontVao);
        glBindTexture(GL_TEXTURE_2D, mFontTextureId);
        glUseProgram(mTextureShaderId);
        //uniform渡さなくても描ける。それがなぞ。
        GLuint textureLocation = glGetUniformLocation(mTextureShaderId, "uTex");
        glUniform1i(textureLocation, 0);
        GLuint scaleLocation = glGetUniformLocation(mTextureShaderId, "uScale");
        //文字のサイズを指定する
        glUniform3f(scaleLocation, 0.2, 0.2, 0.2);
 
        matrixLocation = glGetUniformLocation(mTextureShaderId, "uModelViewProj");
        glUniformMatrix4fv(matrixLocation, 1, GL_FALSE, glm::value_ptr(m_modelview_proj_matrix));
        colorLocation = glGetUniformLocation(mTextureShaderId, "uColor");
        glUniform4f(colorLocation, color_x.r, color_x.g, color_x.b, color_x.a);
        char target_char = 'x';
        float u = (target_char % 8) / 8.0f;//割るx方向のビットマップフォントの数
        float v = (target_char / 8) / 8.0f;//割るy方向のビットマップフォントの数
        glUniform2f(glGetUniformLocation(mTextureShaderId, "uUvBegin"),u,v);
        glUniform3f(glGetUniformLocation(mTextureShaderId, "uBeginPosition"), COORDINATE_SIZE, 0.0, 0.0);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
        target_char = 'y';
        u = (target_char % 8) / 8.0f;
        v = (target_char / 8) / 8.0f;
         glUniform4f(colorLocation, color_y.r, color_y.g, color_y.b, color_y.a);
        glUniform2f(glGetUniformLocation(mTextureShaderId, "uUvBegin"), u, v);
        glUniform3f(glGetUniformLocation(mTextureShaderId, "uBeginPosition"), 0.0, COORDINATE_SIZE, 0.0);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
        target_char = 'z';
        u = (target_char % 8) / 8.0f;
        v = (target_char / 8) / 8.0f;
        glUniform4f(colorLocation, color_z.r, color_z.g, color_z.b, color_z.a);
        glUniform2f(glGetUniformLocation(mTextureShaderId, "uUvBegin"), u, v);
        glUniform3f(glGetUniformLocation(mTextureShaderId, "uBeginPosition"), 0.0, 0.0, COORDINATE_SIZE);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 
        glUseProgram(0);

描画結果

opengl-textured-font-rendering.png

opengl4

サポートサイト Wikidot.com opengl4