123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- package me.hammerle.snuviengine.api;
- import java.nio.ByteBuffer;
- import me.hammerle.snuviengine.util.Rectangle;
- import me.hammerle.snuviengine.util.Color;
- import org.lwjgl.BufferUtils;
- import static org.lwjgl.opengl.GL11.*;
- import static org.lwjgl.opengl.GL15.*;
- import static org.lwjgl.opengl.GL20.*;
- import static org.lwjgl.opengl.GL30.*;
- public class FontRenderer
- {
- private final static Texture FONT_TEXTURE = new Texture("font.png");
-
- public static final char COLOR_CHAR = '&';
-
- private static final float[] COLORS = new float[128];
- private static final float[] DARK_COLORS = new float[128];
-
- private static final int FONT_SIZE = 8;
- private static final int LINE_STEP = 1;
- private static final float SHADOW_STEP = 1f;
-
- static
- {
- COLORS['0'] = Float.intBitsToFloat(Color.get(0, 0, 0));
- COLORS['1'] = Float.intBitsToFloat(Color.get(0, 0, 170));
- COLORS['2'] = Float.intBitsToFloat(Color.get(0, 170, 0));
- COLORS['3'] = Float.intBitsToFloat(Color.get(0, 170, 170));
- COLORS['4'] = Float.intBitsToFloat(Color.get(170, 0, 0));
- COLORS['5'] = Float.intBitsToFloat(Color.get(170, 0, 170));
- COLORS['6'] = Float.intBitsToFloat(Color.get(255, 170, 0));
- COLORS['7'] = Float.intBitsToFloat(Color.get(170, 170, 170));
- COLORS['8'] = Float.intBitsToFloat(Color.get(85, 85, 85));
- COLORS['9'] = Float.intBitsToFloat(Color.get(85, 85, 255));
- COLORS['a'] = Float.intBitsToFloat(Color.get(85, 255, 85));
- COLORS['b'] = Float.intBitsToFloat(Color.get(85, 255, 255));
- COLORS['c'] = Float.intBitsToFloat(Color.get(255, 85, 85));
- COLORS['d'] = Float.intBitsToFloat(Color.get(255, 85, 255));
- COLORS['e'] = Float.intBitsToFloat(Color.get(255, 255, 85));
- COLORS['f'] = Float.intBitsToFloat(Color.get(255, 255, 255));
-
- float factor = 0.5f;
- DARK_COLORS['0'] = Float.intBitsToFloat(Color.darken(Color.get(0, 0, 0), factor));
- DARK_COLORS['1'] = Float.intBitsToFloat(Color.darken(Color.get(0, 0, 170), factor));
- DARK_COLORS['2'] = Float.intBitsToFloat(Color.darken(Color.get(0, 170, 0), factor));
- DARK_COLORS['3'] = Float.intBitsToFloat(Color.darken(Color.get(0, 170, 170), factor));
- DARK_COLORS['4'] = Float.intBitsToFloat(Color.darken(Color.get(170, 0, 0), factor));
- DARK_COLORS['5'] = Float.intBitsToFloat(Color.darken(Color.get(170, 0, 170), factor));
- DARK_COLORS['6'] = Float.intBitsToFloat(Color.darken(Color.get(255, 170, 0), factor));
- DARK_COLORS['7'] = Float.intBitsToFloat(Color.darken(Color.get(170, 170, 170), factor));
- DARK_COLORS['8'] = Float.intBitsToFloat(Color.darken(Color.get(85, 85, 85), factor));
- DARK_COLORS['9'] = Float.intBitsToFloat(Color.darken(Color.get(85, 85, 255), factor));
- DARK_COLORS['a'] = Float.intBitsToFloat(Color.darken(Color.get(85, 255, 85), factor));
- DARK_COLORS['b'] = Float.intBitsToFloat(Color.darken(Color.get(85, 255, 255), factor));
- DARK_COLORS['c'] = Float.intBitsToFloat(Color.darken(Color.get(255, 85, 85), factor));
- DARK_COLORS['d'] = Float.intBitsToFloat(Color.darken(Color.get(255, 85, 255), factor));
- DARK_COLORS['e'] = Float.intBitsToFloat(Color.darken(Color.get(255, 255, 85), factor));
- DARK_COLORS['f'] = Float.intBitsToFloat(Color.darken(Color.get(255, 255, 255), factor));
- }
-
- private int vao;
- private int vbo;
-
- private float color;
-
- private ByteBuffer buffer = BufferUtils.createByteBuffer(OBJECT_LENGTH);
-
- private final static int MAX_LENGTH = 256;
- private final static int BUFFER_BYTE_LENGTH = 1024 * 1024;
- private final static int OBJECT_LENGTH = 120 * MAX_LENGTH * 2;
-
- private int offset = BUFFER_BYTE_LENGTH - OBJECT_LENGTH;
-
- protected FontRenderer()
- {
- Shader.addTask(() ->
- {
- vao = glGenVertexArrays();
- vbo = glGenBuffers();
- GLHelper.glBindVertexArray(vao);
- GLHelper.glBindBuffer(vbo);
-
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glEnableVertexAttribArray(2);
-
- glVertexAttribPointer(0, 2, GL_FLOAT, false, 20, 0);
- glVertexAttribPointer(1, 2, GL_FLOAT, false, 20, 8);
- glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, true, 20, 16);
- });
- }
- private void addRectangle(float minX, float minY, char c)
- {
- float tMinX = (c & 0xF) / 16.0f;
- float tMinY = (c >> 4) / 16.0f;
- float tMaxX = tMinX + 0.0625f;
- float tMaxY = tMinY + 0.0625f;
- float maxX = minX + FONT_SIZE;
- float maxY = minY + FONT_SIZE;
-
- buffer.putFloat(minX);
- buffer.putFloat(maxY);
- buffer.putFloat(tMinX);
- buffer.putFloat(tMaxY);
- buffer.putFloat(color);
-
- buffer.putFloat(minX);
- buffer.putFloat(minY);
- buffer.putFloat(tMinX);
- buffer.putFloat(tMinY);
- buffer.putFloat(color);
-
- buffer.putFloat(maxX);
- buffer.putFloat(maxY);
- buffer.putFloat(tMaxX);
- buffer.putFloat(tMaxY);
- buffer.putFloat(color);
-
- buffer.putFloat(maxX);
- buffer.putFloat(maxY);
- buffer.putFloat(tMaxX);
- buffer.putFloat(tMaxY);
- buffer.putFloat(color);
-
- buffer.putFloat(minX);
- buffer.putFloat(minY);
- buffer.putFloat(tMinX);
- buffer.putFloat(tMinY);
- buffer.putFloat(color);
-
- buffer.putFloat(maxX);
- buffer.putFloat(minY);
- buffer.putFloat(tMaxX);
- buffer.putFloat(tMinY);
- buffer.putFloat(color);
- }
-
- public float drawString(float x, float y, boolean shadow, String s)
- {
- GLHelper.glBindBuffer(vbo);
-
- offset += OBJECT_LENGTH;
- if(offset + OBJECT_LENGTH >= BUFFER_BYTE_LENGTH)
- {
- offset = 0;
- glBufferData(GL_ARRAY_BUFFER, BUFFER_BYTE_LENGTH, GL_STREAM_DRAW);
- }
- buffer = glMapBufferRange(GL_ARRAY_BUFFER, offset, OBJECT_LENGTH, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT, buffer);
- if(buffer == null)
- {
- return y;
- }
-
- if(shadow)
- {
- addString(x + SHADOW_STEP, y + SHADOW_STEP, DARK_COLORS, s);
- }
- y = addString(x, y, COLORS, s);
-
- buffer.flip();
- glUnmapBuffer(GL_ARRAY_BUFFER);
-
- GLHelper.glBindVertexArray(vao);
- FONT_TEXTURE.bindTexture();
-
- glDrawArrays(GL_TRIANGLES, offset / 20, buffer.limit() / 20);
- buffer.limit(buffer.capacity());
- return y;
- }
- private float addString(float x, float y, float[] colors, String s)
- {
- int l = Math.min(s.length(), MAX_LENGTH);
-
- float oldX = x;
- color = colors['f'];
- for(int pos = 0; pos < l; pos++)
- {
- char c = s.charAt(pos);
- if(c == COLOR_CHAR)
- {
- pos++;
- if(pos < l)
- {
- int index = s.charAt(pos);
- if(index >= 0 && index <= colors.length)
- {
- color = colors[s.charAt(pos)];
- }
- }
- continue;
- }
- else if(c == '\n')
- {
- y += FONT_SIZE + LINE_STEP;
- x = oldX;
- continue;
- }
- addRectangle(x, y, c);
- x += FONT_SIZE;
- }
- return y + FONT_SIZE + LINE_STEP;
- }
-
- public Rectangle getSize(String s)
- {
- int length = 0;
- int counter = 0;
- for(int i = 0; i < s.length(); i++)
- {
- switch(s.charAt(i))
- {
- case '\n':
- counter++;
- break;
- case COLOR_CHAR:
- i++;
- break;
- default:
- length++;
- }
- }
- return new Rectangle(FONT_SIZE * length, (FONT_SIZE + LINE_STEP) * counter);
- }
-
- public Rectangle getSize(int w, int h)
- {
- return new Rectangle(FONT_SIZE * w, (FONT_SIZE + LINE_STEP) * h);
- }
-
- public float getHeight()
- {
- return FONT_SIZE + LINE_STEP;
- }
- }
|