Home | History | Annotate | Download | only in tests
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.tests;
     18 
     19 import com.badlogic.gdx.Gdx;
     20 import com.badlogic.gdx.graphics.Color;
     21 import com.badlogic.gdx.graphics.GL20;
     22 import com.badlogic.gdx.graphics.OrthographicCamera;
     23 import com.badlogic.gdx.graphics.Texture;
     24 import com.badlogic.gdx.graphics.Texture.TextureFilter;
     25 import com.badlogic.gdx.graphics.g2d.BitmapFont;
     26 import com.badlogic.gdx.graphics.g2d.GlyphLayout;
     27 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
     28 import com.badlogic.gdx.graphics.g2d.TextureRegion;
     29 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
     30 import com.badlogic.gdx.math.MathUtils;
     31 import com.badlogic.gdx.tests.utils.GdxTest;
     32 import com.badlogic.gdx.utils.Align;
     33 
     34 public class BitmapFontDistanceFieldTest extends GdxTest {
     35 
     36 	private static final String TEXT = "Ta";
     37 	private static final Color COLOR = Color.BLACK;
     38 	private static final float[] SCALES = {0.25f, 0.5f, 1, 2, 4};
     39 
     40 	private static class DistanceFieldShader extends ShaderProgram {
     41 		public DistanceFieldShader () {
     42 			super(Gdx.files.internal("data/shaders/distancefield.vert"), Gdx.files.internal("data/shaders/distancefield.frag"));
     43 			if (!isCompiled()) {
     44 				throw new RuntimeException("Shader compilation failed:\n" + getLog());
     45 			}
     46 		}
     47 
     48 		/** @param smoothing a value between 0 and 1 */
     49 		public void setSmoothing (float smoothing) {
     50 			float delta = 0.5f * MathUtils.clamp(smoothing, 0, 1);
     51 			setUniformf("u_lower", 0.5f - delta);
     52 			setUniformf("u_upper", 0.5f + delta);
     53 		}
     54 	}
     55 
     56 	private OrthographicCamera camera;
     57 	private SpriteBatch spriteBatch;
     58 
     59 	private Texture regularTexture;
     60 	private Texture distanceFieldTexture;
     61 	private BitmapFont descriptionFont;
     62 	private BitmapFont regularFont;
     63 	private BitmapFont distanceFieldFont;
     64 	private DistanceFieldShader distanceFieldShader;
     65 	private GlyphLayout layout = new GlyphLayout();
     66 
     67 	@Override
     68 	public void create () {
     69 		camera = new OrthographicCamera();
     70 		spriteBatch = new SpriteBatch();
     71 
     72 		descriptionFont = new BitmapFont(Gdx.files.internal("data/arial-15.fnt"), true);
     73 		descriptionFont.setColor(Color.RED);
     74 
     75 		regularTexture = new Texture(Gdx.files.internal("data/verdana39.png"), true);
     76 		regularFont = new BitmapFont(Gdx.files.internal("data/verdana39.fnt"), new TextureRegion(regularTexture), true);
     77 		regularFont.setColor(COLOR);
     78 
     79 		distanceFieldTexture = new Texture(Gdx.files.internal("data/verdana39distancefield.png"), true);
     80 		distanceFieldFont = new BitmapFont(Gdx.files.internal("data/verdana39distancefield.fnt"), new TextureRegion(
     81 			distanceFieldTexture), true);
     82 		distanceFieldFont.setColor(COLOR);
     83 
     84 		distanceFieldShader = new DistanceFieldShader();
     85 		ShaderProgram.pedantic = false; // Useful when debugging this test
     86 	}
     87 
     88 	@Override
     89 	public void render () {
     90 		Gdx.gl.glClearColor(1, 1, 1, 1);
     91 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
     92 
     93 		spriteBatch.begin();
     94 
     95 		int x = 10;
     96 		x += drawFont(regularFont, "Regular font\nNearest filter", false, false, 0, x);
     97 		x += drawFont(regularFont, "Regular font\nLinear filter", true, false, 0, x);
     98 		x += drawFont(regularFont, "Regular font\nCustom shader", true, true, 1.0f, x);
     99 		x += drawFont(distanceFieldFont, "Distance field\nCustom shader", true, true, 1 / 8f, x);
    100 		x += drawFont(distanceFieldFont, "Distance field\nShowing distance field", false, false, 0, x);
    101 
    102 		spriteBatch.end();
    103 	}
    104 
    105 	private int drawFont (BitmapFont font, String description, boolean linearFiltering, boolean useShader, float smoothing, int x) {
    106 		int y = 10;
    107 		float maxWidth = 0;
    108 
    109 		spriteBatch.setShader(null);
    110 		descriptionFont.draw(spriteBatch, description, x, y);
    111 		spriteBatch.flush();
    112 		y += 10 + 2 * descriptionFont.getLineHeight();
    113 
    114 		// set filters for each page
    115 		TextureFilter minFilter = linearFiltering ? TextureFilter.MipMapLinearNearest : TextureFilter.Nearest;
    116 		TextureFilter magFilter = linearFiltering ? TextureFilter.Linear : TextureFilter.Nearest;
    117 		for (int i = 0; i < font.getRegions().size; i++) {
    118 			font.getRegion(i).getTexture().setFilter(minFilter, magFilter);
    119 		}
    120 
    121 		if (useShader) {
    122 			spriteBatch.setShader(distanceFieldShader);
    123 		} else {
    124 			spriteBatch.setShader(null);
    125 		}
    126 
    127 		for (float scale : SCALES) {
    128 			font.getData().setScale(scale);
    129 			layout.setText(font, TEXT);
    130 			maxWidth = Math.max(maxWidth, layout.width);
    131 			if (useShader) {
    132 				distanceFieldShader.setSmoothing(smoothing / scale);
    133 			}
    134 			font.draw(spriteBatch, layout, x, y);
    135 			y += font.getLineHeight();
    136 			spriteBatch.flush();
    137 		}
    138 		return (int)Math.ceil(maxWidth);
    139 	}
    140 
    141 	private float getBaselineShift (float shift) {
    142 		return shift;
    143 	}
    144 
    145 	@Override
    146 	public void resize (int width, int height) {
    147 		super.resize(width, height);
    148 		camera.setToOrtho(true, width, height);
    149 		spriteBatch.setTransformMatrix(camera.view);
    150 		spriteBatch.setProjectionMatrix(camera.projection);
    151 	}
    152 
    153 	@Override
    154 	public void dispose () {
    155 		spriteBatch.dispose();
    156 		regularTexture.dispose();
    157 		distanceFieldTexture.dispose();
    158 		descriptionFont.dispose();
    159 		regularFont.dispose();
    160 		distanceFieldFont.dispose();
    161 		distanceFieldShader.dispose();
    162 	}
    163 }
    164