diff --git a/font.lua b/font.lua new file mode 100644 index 0000000..c9f3c20 --- /dev/null +++ b/font.lua @@ -0,0 +1,95 @@ +local _math = require "_math" +local mat4 = _math.mat4 + +local pixel_font_data = love.filesystem.newFileData("pixel_font.glsl") +local vertex_font_data = love.filesystem.newFileData("vertex_font.glsl") +local shader_font = love.graphics.newShader(pixel_font_data, vertex_font_data) + +local fonts = { + ter_6x12 = { + path = "font/terminus_128x64_6x12.data", + texture_width = 128, + texture_height = 64, + glyph_width = 6, + glyph_height = 12, + }, + ter_8x16 = { + path = "font/terminus_128x128_8x16.data", + texture_width = 128, + texture_height = 128, + glyph_width = 8, + glyph_height = 16, + }, + ter_10x18 = { + path = "font/terminus_256x128_10x18.data", + texture_width = 256, + texture_height = 128, + glyph_width = 10, + glyph_height = 18, + }, + ter_12x24 = { + path = "font/terminus_256x128_12x24.data", + texture_width = 256, + texture_height = 128, + glyph_width = 12, + glyph_height = 24, + } +} + +local load_font = function(desc) + local file_data = love.filesystem.newFileData(desc.path) + local image_data = love.image.newImageData(desc.texture_width, desc.texture_height, "r8", file_data) + local texture = love.graphics.newTexture(image_data) + texture:setFilter("nearest", "nearest") + local font = { + texture = texture, + texture_width = desc.texture_width, + texture_height = desc.texture_height, + glyph_width = desc.glyph_width, + glyph_height = desc.glyph_height, + stride = math.floor(desc.texture_width / desc.glyph_width), + } + return font +end + +local glyph_coordinate = function(font, ord) + local c = ord - 32 + local x = c % font.stride + local y = math.floor(c / font.stride) + return {x, y} +end + +local glyph_transform = function(font, x, y) + local transform = ( + mat4.scaling(font.glyph_width, font.glyph_height, 0) + * mat4.translation(x, -y, 0) + * mat4.scaling(2 / 1024, 2 / 1024, 0) + * mat4.translation(-1, 1, 0) + ) + return transform +end + +local draw_string = function(font, s, x, y) + love.graphics.setCanvas() + love.graphics.setShader(shader_font) + shader_font:send("texture_sampler", font.texture) + love.graphics.setDepthMode("always", false) + shader_font:send("cell", {font.glyph_width / font.texture_width, font.glyph_height / font.texture_height}) + + for i = 1, #s do + local c = s:byte(i) + if c ~= 32 then + shader_font:send("transform", "column", glyph_transform(font, x, y).data) + shader_font:send("glyph", glyph_coordinate(font, c)) + love.graphics.drawFromShader(screen_index_buffer, 3 * 2, 1, 1) + end + + x = x + font.glyph_width + end +end + +return { + fonts = fonts, + load_font = load_font, + draw_string = draw_string, +} diff --git a/font/terminus_128x128_8x16.data b/font/terminus_128x128_8x16.data new file mode 100644 index 0000000..00b0555 Binary files /dev/null and b/font/terminus_128x128_8x16.data differ diff --git a/font/terminus_128x64_6x12.data b/font/terminus_128x64_6x12.data new file mode 100644 index 0000000..1639010 Binary files /dev/null and b/font/terminus_128x64_6x12.data differ diff --git a/font/terminus_256x128_10x18.data b/font/terminus_256x128_10x18.data new file mode 100644 index 0000000..246d05a Binary files /dev/null and b/font/terminus_256x128_10x18.data differ diff --git a/font/terminus_256x128_12x24.data b/font/terminus_256x128_12x24.data new file mode 100644 index 0000000..b597181 Binary files /dev/null and b/font/terminus_256x128_12x24.data differ diff --git a/main.lua b/main.lua index 639e4d9..ee6f79d 100644 --- a/main.lua +++ b/main.lua @@ -16,6 +16,9 @@ local scene_noodle = require 'scene.noodle.noodle' local scene_sci_fi_ship = require 'scene.sci_fi_ship.sci_fi_ship' local scene_shadow_test = require 'scene.shadow_test.shadow_test' +local font = require 'font' +local terminus_font + local scenes = { sci_fi_ship = { descriptor = scene_sci_fi_ship.descriptor, @@ -80,6 +83,8 @@ function love.load(args) g_shadow_canvas = love.graphics.newCanvas(2048, 2048, {format = "r32f"}) load_screen_shader() + + terminus_font = font.load_font(font.fonts.ter_10x18) end local rotation = 0.0 @@ -128,4 +133,6 @@ function love.draw() -- love.graphics.setShader(screen_shader) -- screen_shader:send("g_sampler", g_shadow_canvas) -- love.graphics.drawFromShader(screen_index_buffer, 3 * 2, 1, 1) + + font.draw_string(terminus_font, "asdf test 1234", 10, 10) end diff --git a/pixel_font.glsl b/pixel_font.glsl new file mode 100644 index 0000000..27acd84 --- /dev/null +++ b/pixel_font.glsl @@ -0,0 +1,19 @@ +#pragma language glsl3 + +layout (location = 0) out vec4 g_color; + +uniform sampler2D texture_sampler; + +in vec4 PixelTexture; + +uniform vec2 cell; +uniform vec2 glyph; + +void pixelmain() +{ + vec4 sample = texture(texture_sampler, PixelTexture.xy * cell + cell * glyph); + float px = sample.x == 0.0 ? 0.0 : 1.0; + + g_color = vec4(vec3(px), 1.0); + //g_color = vec4(1, 0, 0, 1.0); +} diff --git a/vertex_font.glsl b/vertex_font.glsl new file mode 100644 index 0000000..7ef4162 --- /dev/null +++ b/vertex_font.glsl @@ -0,0 +1,21 @@ +#pragma language glsl3 + +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 + +uniform mat4 transform; + +out vec4 PixelTexture; + +void vertexmain() +{ + 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); + + love_Position = transform * vec4(vertex, 0.0, 1.0); +}