Skip to main content
updated project URL as codeplex is going offline soon, moved raw URL into a text link, added code markdown
Source Link
Pikalek
  • 12.5k
  • 5
  • 45
  • 52

As far as I know, glVertex*glVertex*, glNormal*glNormal*, glTexCoord*glTexCoord* are considered obsolete (like display lists) and are not recommended to use.

ThisThis gives a comprehensive overview of various OpenGL-based text rendering techniques: https://stackoverflow.com/questions/5262951/what-is-state-of-the-art-for-text-rendering-in-opengl-as-of-version-4-1

Offline: 0) prepare a font texture atlas (with tightly packed glyphs, block-compressed) and remember glyph data (position, size, unicode => glyph index mapping); for these purposes I use MakeSpriteFont from DirectX Tool KitDirectX Tool Kit.

  1. load the font texture and glyph data (submit data of each mipmap level to glCompressedTexSubImage2DglCompressedTexSubImage2D);
  2. create a dynamic vertex buffer (GL_DYNAMIC_DRAWGL_DYNAMIC_DRAW) for holding MAX_TEXT_LENGTHMAX_TEXT_LENGTH vertices;

As far as I know, glVertex*, glNormal*, glTexCoord* are considered obsolete (like display lists) and are not recommended to use.

This gives a comprehensive overview of various OpenGL-based text rendering techniques: https://stackoverflow.com/questions/5262951/what-is-state-of-the-art-for-text-rendering-in-opengl-as-of-version-4-1

Offline: 0) prepare a font texture atlas (with tightly packed glyphs, block-compressed) and remember glyph data (position, size, unicode => glyph index mapping); for these purposes I use MakeSpriteFont from DirectX Tool Kit.

  1. load the font texture and glyph data (submit data of each mipmap level to glCompressedTexSubImage2D);
  2. create a dynamic vertex buffer (GL_DYNAMIC_DRAW) for holding MAX_TEXT_LENGTH vertices;

As far as I know, glVertex*, glNormal*, glTexCoord* are considered obsolete (like display lists) and are not recommended to use.

This gives a comprehensive overview of various OpenGL-based text rendering techniques:

Offline: 0) prepare a font texture atlas (with tightly packed glyphs, block-compressed) and remember glyph data (position, size, unicode => glyph index mapping); for these purposes I use MakeSpriteFont from DirectX Tool Kit.

  1. load the font texture and glyph data (submit data of each mipmap level to glCompressedTexSubImage2D);
  2. create a dynamic vertex buffer (GL_DYNAMIC_DRAW) for holding MAX_TEXT_LENGTH vertices;
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link
Added a short description of the method and the relevand bits of source code
Source Link

The details of the technique I'm using:

Offline: 0) prepare a font texture atlas (with tightly packed glyphs, block-compressed) and remember glyph data (position, size, unicode => glyph index mapping); for these purposes I use MakeSpriteFont from DirectX Tool Kit.

At launch time:

  1. load the font texture and glyph data (submit data of each mipmap level to glCompressedTexSubImage2D);
  2. create a dynamic vertex buffer (GL_DYNAMIC_DRAW) for holding MAX_TEXT_LENGTH vertices;

At draw time: 4) parse the submitted text string and update the VBO using the glyph data; 5) draw the points from VBO

glBindBuffer( GL_ARRAY_BUFFER, dynamicVBO_id );
glDrawArrays( GL_POINTS, 0/*first vertex*/, vertexCount/*==character count*/ );

My vertex shader code:

#version 420 core

in vec4 a_texCoord0;    // .xy - center position, .zw - width and height
in vec4 a_texCoord1;    // st coords for top left and bottom right corners

out VSO {
    vec4 xy_wh;
    vec4 tl_br;
} outputs;

void main()
{
    // gl_Position will be written by geometry shader
    outputs.xy_wh = a_texCoord0;
    outputs.tl_br = a_texCoord1;
}

Geometry shader code:

#version 420 core

layout(points) in;
layout(triangle_strip, max_vertices=4) out;

in VSO {
    vec4 xy_wh;
    vec4 tl_br; // UVs for top left and bottom right corners
} inputs[];

out GSO {
    vec2 texCoord;
} outputs;

void main()
{
    vec2    pos = inputs[0].xy_wh.xy;
    float   width = inputs[0].xy_wh.z;
    float   height = inputs[0].xy_wh.w;

    vec2    tl = inputs[0].tl_br.xy;
    vec2    br = inputs[0].tl_br.zw;

    gl_Position = vec4( pos.x, pos.y, 0.0f, 1.0f );
    outputs.texCoord = vec2( tl.x, tl.y );
    EmitVertex();

    gl_Position = vec4( pos.x + width, pos.y, 0.0f, 1.0f );
    outputs.texCoord = vec2( br.x, tl.y );
    EmitVertex();

    gl_Position = vec4( pos.x, pos.y - height, 0.0f, 1.0f );
    outputs.texCoord = vec2( tl.x, br.y );
    EmitVertex();

    gl_Position = vec4( pos.x + width, pos.y - height, 0.0f, 1.0f );
    outputs.texCoord = vec2( br.x, br.y );
    EmitVertex();

    EndPrimitive();
}

Fragment shader code:

#version 420 core

in GSO {
    vec2 texCoord;
} inputs;

out vec4 o_pixelColor;

uniform sampler2D s_font;

void main()
{
    vec4 textureColor = texture( s_font, inputs.texCoord ).rgba;
    if( textureColor.w < 1.0/255.0 ) {
        discard;
    }
    o_pixelColor = textureColor;
}

I'm not in any way proficient in OpenGL.

The details of the technique I'm using:

Offline: 0) prepare a font texture atlas (with tightly packed glyphs, block-compressed) and remember glyph data (position, size, unicode => glyph index mapping); for these purposes I use MakeSpriteFont from DirectX Tool Kit.

At launch time:

  1. load the font texture and glyph data (submit data of each mipmap level to glCompressedTexSubImage2D);
  2. create a dynamic vertex buffer (GL_DYNAMIC_DRAW) for holding MAX_TEXT_LENGTH vertices;

At draw time: 4) parse the submitted text string and update the VBO using the glyph data; 5) draw the points from VBO

glBindBuffer( GL_ARRAY_BUFFER, dynamicVBO_id );
glDrawArrays( GL_POINTS, 0/*first vertex*/, vertexCount/*==character count*/ );

My vertex shader code:

#version 420 core

in vec4 a_texCoord0;    // .xy - center position, .zw - width and height
in vec4 a_texCoord1;    // st coords for top left and bottom right corners

out VSO {
    vec4 xy_wh;
    vec4 tl_br;
} outputs;

void main()
{
    // gl_Position will be written by geometry shader
    outputs.xy_wh = a_texCoord0;
    outputs.tl_br = a_texCoord1;
}

Geometry shader code:

#version 420 core

layout(points) in;
layout(triangle_strip, max_vertices=4) out;

in VSO {
    vec4 xy_wh;
    vec4 tl_br; // UVs for top left and bottom right corners
} inputs[];

out GSO {
    vec2 texCoord;
} outputs;

void main()
{
    vec2    pos = inputs[0].xy_wh.xy;
    float   width = inputs[0].xy_wh.z;
    float   height = inputs[0].xy_wh.w;

    vec2    tl = inputs[0].tl_br.xy;
    vec2    br = inputs[0].tl_br.zw;

    gl_Position = vec4( pos.x, pos.y, 0.0f, 1.0f );
    outputs.texCoord = vec2( tl.x, tl.y );
    EmitVertex();

    gl_Position = vec4( pos.x + width, pos.y, 0.0f, 1.0f );
    outputs.texCoord = vec2( br.x, tl.y );
    EmitVertex();

    gl_Position = vec4( pos.x, pos.y - height, 0.0f, 1.0f );
    outputs.texCoord = vec2( tl.x, br.y );
    EmitVertex();

    gl_Position = vec4( pos.x + width, pos.y - height, 0.0f, 1.0f );
    outputs.texCoord = vec2( br.x, br.y );
    EmitVertex();

    EndPrimitive();
}

Fragment shader code:

#version 420 core

in GSO {
    vec2 texCoord;
} inputs;

out vec4 o_pixelColor;

uniform sampler2D s_font;

void main()
{
    vec4 textureColor = texture( s_font, inputs.texCoord ).rgba;
    if( textureColor.w < 1.0/255.0 ) {
        discard;
    }
    o_pixelColor = textureColor;
}

I'm not in any way proficient in OpenGL.

Source Link
Loading