4

I'm trying to rendering smooth scalable bitmap fonts. After checking this question one of the answers mentioned using distance field fonts.

I'm doing exactly as mentioned in LibGDX wiki article about distance filed fonts. However I can't get it working. Fonts are rendered hazy.

example preview

Here's the code I used to generate this output

public class FontRenderTest implements ApplicationListener {
private Texture texture;
private SpriteBatch spriteBatch;
private BitmapFont font;

@Override
public void create() {
    spriteBatch = new SpriteBatch();

    Texture texture = new Texture(Gdx.files.internal("Raleway.png"), true); // true enables mipmaps
    texture.setFilter(TextureFilter.MipMapLinearNearest, TextureFilter.Linear); // linear filtering in nearest mipmap image

    font = new BitmapFont(Gdx.files.internal("Raleway.fnt"), new TextureRegion(texture), false);
}


@Override
public void render() {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    spriteBatch.begin();
    font.draw(spriteBatch, "This is hazy !!", 100, 150);
    spriteBatch.end();

}
}

I'm not sure if I properly understand the function of distance field font. If anyone could explain how to render font smooth.

Community
  • 1
  • 1
Ashraf Saleh
  • 404
  • 1
  • 3
  • 19
  • You're rendering the distance-field directly, instead of calculating the distance to the closet point on the edge. You need a fragment shader to do this. – kusma Jun 23 '14 at 12:00

2 Answers2

5

I think it needs a shader and if I recall right the shaders require GL20. As it said in the wiki you would need .frag and .vert files. I modified your code with the help from this Libgdx test: http://git.io/-yAmNg .

It looks like this with different smoothing.

It looks like this with different smoothing.

public class FontRenderTest implements ApplicationListener {                                                                
private Texture texture;                                                                                                    
private SpriteBatch spriteBatch;                                                                                            
private BitmapFont font;                                                                                                    
private DistanceFieldShader distanceFieldShader;                                                                            
private static class DistanceFieldShader extends ShaderProgram {                                                            
    public DistanceFieldShader () {                                                                                         
        // The vert and frag files are copied from http://git.io/yK63lQ (vert) and http://git.io/hAcw9Q (the frag)          
        super(Gdx.files.internal("data/shaders/distancefield.vert"), Gdx.files.internal("data/shaders/distancefield.frag"));
        if (!isCompiled()) {                                                                                                
            throw new RuntimeException("Shader compilation failed:\n" + getLog());                                          
        }                                                                                                                   
    }                                                                                                                       

    /** @param smoothing a value between 0 and 1 */                                                                         
    public void setSmoothing (float smoothing) {                                                                            
        float delta = 0.5f * MathUtils.clamp(smoothing, 0, 1);                                                              
        setUniformf("u_lower", 0.5f - delta);                                                                               
        setUniformf("u_upper", 0.5f + delta);                                                                               
    }                                                                                                                       
}                                                                                                                           
    @Override                                                                                                                   
    public void create() {                                                                                                      
        spriteBatch = new SpriteBatch();                                                                                        

        Texture texture = new Texture(Gdx.files.internal("hiero.png"), true); // true enables mipmaps                           
        texture.setFilter(TextureFilter.MipMapLinearNearest, TextureFilter.Linear); // linear filtering in nearest mipmap image 

        font = new BitmapFont(Gdx.files.internal("hiero.fnt"), new TextureRegion(texture), false);                              
        distanceFieldShader = new DistanceFieldShader();                                                                        
    }
       @Override                                                                             
   public void render() {                                                                
       Gdx.gl.glClearColor(0, 0, 0, 1);                                                  
       Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);                                         

       spriteBatch.begin();                                                              

       spriteBatch.setShader(distanceFieldShader);                                       
       font.draw(spriteBatch, "This is pretty sharp !!", 100, 120);                      
       distanceFieldShader.setSmoothing(0f);                                             

       spriteBatch.setShader(distanceFieldShader);                                       
       font.draw(spriteBatch, "This is hazy !!", 100, 150);                              
       distanceFieldShader.setSmoothing(1f);                                             

       spriteBatch.setShader(distanceFieldShader);                                       
       font.draw(spriteBatch, "This is pretty smooth !!", 100, 180);                     
       distanceFieldShader.setSmoothing(1/2f);                                           

       spriteBatch.end();                                                                

   }
  • I thought i can use this technique without a shader using GL10. – Ashraf Saleh Jun 23 '14 at 15:51
  • 2
    Unfortunately all the updated code examples in the wiki are for GL20 since Libgdx dropped the GL10 support so I don’t know if there are any GL10 equivalent. At least I couldn’t find any. – Sampo Pietikäinen Jun 23 '14 at 16:20
1

Use the shader created by DistanceFieldFont.createDistanceFieldShader.

NateS
  • 5,751
  • 4
  • 49
  • 59