• Advertisement
Sign in to follow this  

How to Render Text

This topic is 1231 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Anybody has a Cool Tip on how to start if I want to implement Text input and output and render the whole thing.

 

 

Thanks!

Share this post


Link to post
Share on other sites
Advertisement
cool tip: Google.

Seriously, this topic has been covered more times than I can count. It's super complicated on a production scale (multiple languages, Unicode, IME, high-quality font rendering, etc.) but getting simple ASCII input with a framework library handling input and drawing via a simple bitmap font is easy enough.

This article is an ok approach, though I personally feel that using FreeType is overkill (and a pain in the butt when you have to build it yourself): http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_01

Share this post


Link to post
Share on other sites

I had this problem for a lot time, so I'll help right now, here's my code. It's made for OpenGL 3.0/ES. The main algorithm and drawing methods are here. Just remove some useless stuff and use it.

//
//  Nanocat engine.
//
//  Font loader and renderer..
//
//  Created by Neko Vision on 02/01/2014.
//  Copyright (c) 2014 Neko Vision. All rights reserved.
//
 
#include "Core.h"
#include "SystemShared.h"
#include "AssetManager.h"
#include "MaterialLoader.h"
#include "CoreFont.h"
#include "Renderer.h"
#include "OpenGL.h"
#include "GameMath.h"
 
// Font manager.
ncCoreFontRenderer _font;
 
// Settings.
ncConsoleVariable Font_Size( "font", "size", "Font size.", "0.0625", CVFLAG_NONE );
ncConsoleVariable Font_Width( "font", "width", "Font character width.", "1.0", CVFLAG_NONE );
ncConsoleVariable Font_Height( "font", "height", "Font character height.", "1.0", CVFLAG_NONE );
ncConsoleVariable Font_Skip( "font", "skip", "Font character skip size.", "32", CVFLAG_NONE );
 
 
/*
    Print text somewhere on screen.
*/
void ncCoreFontRenderer::Print2D( ncVec4 color, int x, int y, int size, const char *msg, ... ) {
 
    if( !_opengl.Initialized && !_renderer.Initialized )
        return;
    
    va_list     argptr;
    char        text[256];
 
    va_start( argptr, msg );
    vsnprintf( text, sizeof(text), msg, argptr );
    va_end( argptr );
 
    ulong length = strlen(text);
 
    // Awful.... yea.... I know.
    ncVec2 vertices[FONT_VERTICES];
    ncVec2 UVs[FONT_VERTICES];
 
    zeromem( vertices, sizeof(ncVec2) * FONT_VERTICES );
    zeromem( UVs, sizeof(ncVec2) * FONT_VERTICES );
 
    int i, c = 0;
for ( i = 0; i < length; i++ ) {
 
        // Too much calculations in a loop!?!?!
        
        
        float fheight = Font_Height.GetFloat();
        float fwidth = Font_Width.GetFloat();
 
        ncVec2 vertex_up_left    = ncVec2( x + i * size - 5.0, y - size - fheight );
ncVec2 vertex_up_right   = ncVec2( x + i * size + size + fwidth - 5.0, y - size - fheight );
ncVec2 vertex_down_right = ncVec2( x + i * size + size + fwidth - 5.0, y );
ncVec2 vertex_down_left  = ncVec2( x + i * size - 5.0, y );
 
        char character = text[i] - FONT_CHARACTERSKIP;
 
float uv_x = ( character % 16 ) / 16.0f;
float uv_y = ( character / 16 ) / 16.0f;
 
        float size = Font_Size.GetFloat();
        
ncVec2 uv_up_left    = ncVec2( uv_x, 1 - uv_y - size );
ncVec2 uv_up_right   = ncVec2( uv_x + size, 1 - uv_y - size );
ncVec2 uv_down_right = ncVec2( uv_x + size, 1 - uv_y );
ncVec2 uv_down_left  = ncVec2( uv_x, 1 - uv_y );
 
        // Build character map.
        vertices[c].x = vertex_up_left.x;
        vertices[c].y = vertex_up_left.y;
 
        UVs[c].x = uv_up_left.x;
        UVs[c].y = uv_up_left.y;
 
        c++;
        vertices[c].x = vertex_down_left.x;
        vertices[c].y = vertex_down_left.y;
 
        UVs[c].x = uv_down_left.x;
        UVs[c].y = uv_down_left.y;
 
        c++;
        vertices[c].x = vertex_up_right.x;
        vertices[c].y = vertex_up_right.y;
 
        UVs[c].x = uv_up_right.x;
        UVs[c].y = uv_up_right.y;
 
        c++;
        vertices[c].x = vertex_down_right.x;
        vertices[c].y = vertex_down_right.y;
 
        UVs[c].x = uv_down_right.x;
        UVs[c].y = uv_down_right.y;
 
        c++;
        vertices[c].x = vertex_up_right.x;
        vertices[c].y = vertex_up_right.y;
 
        UVs[c].x = uv_up_right.x;
        UVs[c].y = uv_up_right.y;
 
        c++;
        vertices[c].x = vertex_down_left.x;
        vertices[c].y = vertex_down_left.y;
 
        UVs[c].x = uv_down_left.x;
        UVs[c].y = uv_down_left.y;
 
c++;
}
 
/*
        Real time generation.
    */
    //glDeleteVertexArrays(1, &_font.VAO );
    
    glBindVertexArray( _font.VAO );
    
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, _font.VBO );
glBufferData( GL_ARRAY_BUFFER, sizeof(ncVec2) * FONT_VERTICES, &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(ncVec2), 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
    
glEnableVertexAttribArray( 1 );
glBindBuffer( GL_ARRAY_BUFFER, _font.UV );
glBufferData( GL_ARRAY_BUFFER, sizeof(ncVec2) * FONT_VERTICES, &UVs[0], GL_STATIC_DRAW );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, sizeof(ncVec2), 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
    
glBindVertexArray( 0 );
 
    /*
        Font rendering.
    */
    glEnable(GL_BLEND);
    glBlendFunc( GL_ONE, GL_SRC_ALPHA );
 
glUseProgram( _font.shader.shader_id );
 
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, _font.texture );
 
    // Apply color.
    glUniform3f( _font.colorID, color.x, color.y, color.z );
 
    // Bind vertex object and render font.
    glBindVertexArray( _font.VAO );
glDrawArrays( GL_TRIANGLES, 0, FONT_VERTICES );
    glBindVertexArray( 0 );
    
    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, 0 );
 
glUseProgram( 0 );
 
glDisable( GL_BLEND );
}
 
/*
    Load font system.
*/
void ncCoreFontRenderer::Initialize( void ) {
 
    glGenBuffers( 1, &_font.VBO );
glGenBuffers( 1, &_font.UV );
glGenVertexArrays( 1, &_font.VAO );
 
    _assetmanager.FindShader( "font", &_font.shader );
 
    _font.texture = _materials.Find( "default_font" ).texture.TextureID;
 
    glUseProgram( _font.shader.shader_id );
 
    // Font color.
    _font.colorID = glGetUniformLocation( _font.shader.shader_id, "colorModifier" );
 
    // Font map.
    _font.texID = glGetUniformLocation( _font.shader.shader_id, "font_texture" );
 
    glUniform1i( _font.texID, 0 );
    glUniform3f( _font.colorID, 1.0, 1.0, 1.0 );
 
    glUseProgram(0);
}

Shader code is super simple:

"
 
precision lowp float;
layout(location = 0) in vec2 vertexPosition_screenspace;
layout(location = 1) in vec2 vertexUV;
 
out vec2 UV;
 
void main(){
vec2 vphn = vertexPosition_screenspace - vec2(400.0,300.0); 
vphn /= vec2(400.0,300.0);
gl_Position = vec4(vphn,0.0,1.0);
 
UV = vertexUV;
}
 
"
 
precision lowp float;
in vec2 UV;
out vec4 color;
 
uniform sampler2D font_texture;
uniform vec3 colorModifier;
 
void main(){
mediump vec4 colorf = texture( font_texture, UV );
color = colorf * vec4(colorModifier, 1.0);
}
 
"

And the last thing: here's bitmap font image:

http://cl.ly/3j1A0i211R2n

Edited by NekoCode

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement