font rendering
This commit is contained in:
parent
e6d4fbd182
commit
a0e922975a
3
Makefile
3
Makefile
@ -19,7 +19,8 @@ LDFLAGS += $(shell pkg-config --libs glfw3)
|
|||||||
OBJS = \
|
OBJS = \
|
||||||
src/gl.o \
|
src/gl.o \
|
||||||
src/opengl.o \
|
src/opengl.o \
|
||||||
src/test.o
|
src/test.o \
|
||||||
|
src/font.o
|
||||||
|
|
||||||
all: test.so
|
all: test.so
|
||||||
|
|
||||||
|
|||||||
BIN
font/terminus_128x128_8x16.data
Normal file
BIN
font/terminus_128x128_8x16.data
Normal file
Binary file not shown.
BIN
font/terminus_128x64_6x12.data
Normal file
BIN
font/terminus_128x64_6x12.data
Normal file
Binary file not shown.
BIN
font/terminus_256x128_10x18.data
Normal file
BIN
font/terminus_256x128_10x18.data
Normal file
Binary file not shown.
BIN
font/terminus_256x128_12x24.data
Normal file
BIN
font/terminus_256x128_12x24.data
Normal file
Binary file not shown.
56
include/font.h
Normal file
56
include/font.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace font {
|
||||||
|
|
||||||
|
struct font_desc {
|
||||||
|
char const * const path;
|
||||||
|
int const texture_width;
|
||||||
|
int const texture_height;
|
||||||
|
int const glyph_width;
|
||||||
|
int const glyph_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
font_desc const ter_6x12 = {
|
||||||
|
.path = "font/terminus_128x64_6x12.data",
|
||||||
|
.texture_width = 128,
|
||||||
|
.texture_height = 64,
|
||||||
|
.glyph_width = 6,
|
||||||
|
.glyph_height = 12,
|
||||||
|
};
|
||||||
|
font_desc const ter_8x16 = {
|
||||||
|
.path = "font/terminus_128x128_8x16.data",
|
||||||
|
.texture_width = 128,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 8,
|
||||||
|
.glyph_height = 16,
|
||||||
|
};
|
||||||
|
font_desc const ter_10x18 = {
|
||||||
|
.path = "font/terminus_256x128_10x18.data",
|
||||||
|
.texture_width = 256,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 10,
|
||||||
|
.glyph_height = 18,
|
||||||
|
};
|
||||||
|
font_desc const ter_12x24 = {
|
||||||
|
.path = "font/terminus_256x128_12x24.data",
|
||||||
|
.texture_width = 256,
|
||||||
|
.texture_height = 128,
|
||||||
|
.glyph_width = 12,
|
||||||
|
.glyph_height = 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct font {
|
||||||
|
font_desc const * desc;
|
||||||
|
unsigned int texture;
|
||||||
|
int stride;
|
||||||
|
struct {
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
} cell;
|
||||||
|
};
|
||||||
|
|
||||||
|
void load_element_buffer();
|
||||||
|
void load_shader();
|
||||||
|
font load_font(font_desc const& desc);
|
||||||
|
void draw_string(font const& font, char const * const s, int x, int y);
|
||||||
|
}
|
||||||
2
main.lua
2
main.lua
@ -58,6 +58,6 @@ function love.run()
|
|||||||
love.graphics.present()
|
love.graphics.present()
|
||||||
love.timer.sleep(0.001)
|
love.timer.sleep(0.001)
|
||||||
local fps = love.timer.getFPS( )
|
local fps = love.timer.getFPS( )
|
||||||
print(fps)
|
--print(fps)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
set -eux
|
set -eux
|
||||||
cd ./minecraft/gen
|
cd ./minecraft/gen
|
||||||
python mc.py ~/Love2DWorld/region/r.0.0.mcr ../region.0.0 &
|
PYTHON=pypy3.11
|
||||||
python mc.py ~/Love2DWorld/region/r.-1.-1.mcr ../region.-1.-1 &
|
$PYTHON mc.py ~/Love2DWorld/region/r.0.0.mcr ../region.0.0 &
|
||||||
python mc.py ~/Love2DWorld/region/r.0.-1.mcr ../region.0.-1 &
|
$PYTHON mc.py ~/Love2DWorld/region/r.-1.-1.mcr ../region.-1.-1 &
|
||||||
python mc.py ~/Love2DWorld/region/r.-1.0.mcr ../region.-1.0 &
|
$PYTHON mc.py ~/Love2DWorld/region/r.0.-1.mcr ../region.0.-1 &
|
||||||
|
$PYTHON mc.py ~/Love2DWorld/region/r.-1.0.mcr ../region.-1.0 &
|
||||||
|
|||||||
18
shader/font.frag
Normal file
18
shader/font.frag
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
uniform sampler2D TextureSampler;
|
||||||
|
|
||||||
|
uniform vec2 Cell;
|
||||||
|
uniform vec2 Glyph;
|
||||||
|
|
||||||
|
out vec4 g_color;
|
||||||
|
|
||||||
|
in vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 sample = texture(TextureSampler, PixelTexture.xy * Cell + Cell * Glyph);
|
||||||
|
float px = sample.x == 0.0 ? 0.0 : 1.0;
|
||||||
|
|
||||||
|
g_color = vec4(vec3(px), 1.0);
|
||||||
|
}
|
||||||
39
shader/font.vert
Normal file
39
shader/font.vert
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
const vec2 vtx[4] = vec2[](vec2(-1.0, 1.0), // tl
|
||||||
|
vec2( 1.0, 1.0), // tr
|
||||||
|
vec2( 1.0, -1.0), // br
|
||||||
|
vec2(-1.0, -1.0)); // bl
|
||||||
|
|
||||||
|
/*
|
||||||
|
tl tr
|
||||||
|
br
|
||||||
|
|
||||||
|
0 1 2
|
||||||
|
tr tl br
|
||||||
|
1 0 2
|
||||||
|
|
||||||
|
tl
|
||||||
|
bl br
|
||||||
|
|
||||||
|
2 1 3
|
||||||
|
br tl bl
|
||||||
|
2 0 3
|
||||||
|
|
||||||
|
1 0 2 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
uniform mat4 Transform;
|
||||||
|
|
||||||
|
out vec4 PixelTexture;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 vertex = vtx[gl_VertexID];
|
||||||
|
|
||||||
|
PixelTexture = vec4(vertex * vec2(0.5, -0.5) + 0.5, 0, 0);
|
||||||
|
|
||||||
|
vertex = vertex * vec2(0.5, 0.5) + vec2(0.5, -0.5);
|
||||||
|
|
||||||
|
gl_Position = Transform * vec4(vertex, 0.0, 1.0);
|
||||||
|
}
|
||||||
152
src/font.cpp
Normal file
152
src/font.cpp
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
#include "glad/gl.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
namespace font {
|
||||||
|
|
||||||
|
struct location {
|
||||||
|
struct {
|
||||||
|
unsigned int transform;
|
||||||
|
unsigned int texture_sampler;
|
||||||
|
unsigned int cell;
|
||||||
|
unsigned int glyph;
|
||||||
|
} uniform;
|
||||||
|
};
|
||||||
|
|
||||||
|
static location location;
|
||||||
|
|
||||||
|
static unsigned int font_program = -1;
|
||||||
|
|
||||||
|
static unsigned int vertex_array_object = -1;
|
||||||
|
static unsigned int index_buffer = -1;
|
||||||
|
|
||||||
|
void load_element_buffer()
|
||||||
|
{
|
||||||
|
uint8_t const data[] = {
|
||||||
|
1, 0, 2, 3,
|
||||||
|
};
|
||||||
|
int const data_size = (sizeof (data));
|
||||||
|
|
||||||
|
glGenBuffers(1, &index_buffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, data_size, data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vertex_array_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_shader()
|
||||||
|
{
|
||||||
|
unsigned int program = compile_from_files("shader/font.vert",
|
||||||
|
NULL, // geom
|
||||||
|
"shader/font.frag");
|
||||||
|
|
||||||
|
location.uniform.transform = glGetUniformLocation(program, "Transform");
|
||||||
|
location.uniform.texture_sampler = glGetUniformLocation(program, "TextureSampler");
|
||||||
|
location.uniform.cell = glGetUniformLocation(program, "Cell");
|
||||||
|
location.uniform.glyph = glGetUniformLocation(program, "Glyph");
|
||||||
|
printf("font uniforms:\n transform %u\n texture_sampler %u\n cell %u\n glyph %u\n",
|
||||||
|
location.uniform.transform,
|
||||||
|
location.uniform.texture_sampler,
|
||||||
|
location.uniform.cell,
|
||||||
|
location.uniform.glyph
|
||||||
|
);
|
||||||
|
|
||||||
|
font_program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
font load_font(font_desc const& desc)
|
||||||
|
{
|
||||||
|
unsigned int texture;
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int texture_data_size;
|
||||||
|
void * texture_data = read_file(desc.path, &texture_data_size);
|
||||||
|
assert(texture_data != nullptr);
|
||||||
|
|
||||||
|
int width = desc.texture_width;
|
||||||
|
int height = desc.texture_height;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
|
free(texture_data);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return (font){
|
||||||
|
.desc = &desc,
|
||||||
|
.texture = texture,
|
||||||
|
.stride = desc.texture_width / desc.glyph_width,
|
||||||
|
.cell = { (float)desc.glyph_width / (float)desc.texture_width,
|
||||||
|
(float)desc.glyph_height / (float)desc.texture_height },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static XMFLOAT2 glyph_coordinate(font const& font, int ord)
|
||||||
|
{
|
||||||
|
int c = ord - 32;
|
||||||
|
int x = c % font.stride;
|
||||||
|
int y = c / font.stride;
|
||||||
|
XMVECTOR coord = XMVectorSet(x, y, 0, 0);
|
||||||
|
XMFLOAT2 coordf;
|
||||||
|
XMStoreFloat2(&coordf, coord);
|
||||||
|
return coordf;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static XMFLOAT4X4 glyph_transform(font const& font, int x, int y)
|
||||||
|
{
|
||||||
|
XMMATRIX transform =
|
||||||
|
XMMatrixScaling(font.desc->glyph_width, font.desc->glyph_height, 0)
|
||||||
|
* XMMatrixTranslation(x, -y, 0)
|
||||||
|
* XMMatrixScaling(2.0f / 1024.0f, 2.0f / 1024.0f, 0)
|
||||||
|
* XMMatrixTranslation(-1, 1, 0);
|
||||||
|
XMFLOAT4X4 transformf;
|
||||||
|
XMStoreFloat4x4(&transformf, transform);
|
||||||
|
return transformf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_string(font const& font, char const * const s, int x, int y)
|
||||||
|
{
|
||||||
|
glUseProgram(font_program);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, font.texture);
|
||||||
|
|
||||||
|
glUniform1i(location.uniform.texture_sampler, 0);
|
||||||
|
glUniform2fv(location.uniform.cell, 1, (float *)&font.cell);
|
||||||
|
|
||||||
|
glBindVertexArray(vertex_array_object);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (s[i] != 0) {
|
||||||
|
char c = s[i];
|
||||||
|
if (c <= 0x20 || c > 0x7f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
XMFLOAT4X4 transform = glyph_transform(font, x, y);
|
||||||
|
glUniformMatrix4fv(location.uniform.transform, 1, GL_FALSE, (float *)&transform);
|
||||||
|
XMFLOAT2 glyph = glyph_coordinate(font, c);
|
||||||
|
glUniform2fv(location.uniform.glyph, 1, (float *)&glyph);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
|
||||||
|
|
||||||
|
x += font.desc->glyph_width;
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/test.cpp
13
src/test.cpp
@ -6,6 +6,7 @@
|
|||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
#include "directxmath/directxmath.h"
|
#include "directxmath/directxmath.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
#include "data.inc"
|
#include "data.inc"
|
||||||
|
|
||||||
@ -246,6 +247,8 @@ struct view_state {
|
|||||||
|
|
||||||
view_state view_state;
|
view_state view_state;
|
||||||
|
|
||||||
|
font::font ter_8x16 = {};
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
|
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
|
||||||
@ -266,6 +269,14 @@ void load()
|
|||||||
//unsigned int textures_layout = glGetUniformBlockIndex(test_program, "TexturesLayout");
|
//unsigned int textures_layout = glGetUniformBlockIndex(test_program, "TexturesLayout");
|
||||||
//glUniformBlockBinding(test_program, textures_layout, 0);
|
//glUniformBlockBinding(test_program, textures_layout, 0);
|
||||||
//printf("textures_layout %d\n", textures_layout);
|
//printf("textures_layout %d\n", textures_layout);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// font
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
font::load_element_buffer();
|
||||||
|
font::load_shader();
|
||||||
|
ter_8x16 = font::load_font(font::ter_8x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(float lx, float ly, float rx, float ry, float tl, float tr,
|
void update(float lx, float ly, float rx, float ry, float tl, float tr,
|
||||||
@ -357,4 +368,6 @@ void draw()
|
|||||||
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
|
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count, base_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
font::draw_string(ter_8x16, "test", 10, 10);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user