Compare commits
2 Commits
044b405289
...
65b0a40006
Author | SHA1 | Date |
---|---|---|
Jill | 65b0a40006 | |
Jill | 2998463350 |
|
@ -6,14 +6,16 @@ class Funfriend::ChatterContext < Funfriend::WindowContext
|
|||
WINDOW_SIZE = {width: 256, height: 32}
|
||||
DEFAULT_DURATION = 10.0
|
||||
|
||||
PADDING = 10
|
||||
|
||||
def initialize(text : String, position : NamedTuple(x: Int32, y: Int32), duration : Float64 = DEFAULT_DURATION)
|
||||
sheet = FontMan.parse_bm(File.read "assets/fonts/SpaceMono.fnt")
|
||||
|
||||
position_data = FontMan.position_text(text, sheet)
|
||||
|
||||
@window_size = {
|
||||
width: position_data[:width],
|
||||
height: position_data[:height]
|
||||
width: position_data[:width] + PADDING * 2,
|
||||
height: position_data[:height] + PADDING * 2
|
||||
}
|
||||
|
||||
super(
|
||||
|
@ -26,7 +28,7 @@ class Funfriend::ChatterContext < Funfriend::WindowContext
|
|||
window.make_context_current
|
||||
|
||||
@timer = duration
|
||||
@renderer = TextRenderer.new(text, sheet)
|
||||
@renderer = TextRenderer.new(text, sheet, window_size[:width], window_size[:height])
|
||||
|
||||
window.position = {
|
||||
x: position[:x] - window_size[:width]//2,
|
||||
|
@ -41,7 +43,7 @@ class Funfriend::ChatterContext < Funfriend::WindowContext
|
|||
LibGL.clear_color(0.0, 0.0, 0.0, 1.0)
|
||||
LibGL.clear(Buffer::Bit::Color)
|
||||
|
||||
renderer.render(dt, window_size[:width], window_size[:height])
|
||||
renderer.render(dt)
|
||||
end
|
||||
|
||||
def update(dt : Float64)
|
||||
|
|
|
@ -79,6 +79,14 @@ module Funfriend::FontMan
|
|||
}
|
||||
end
|
||||
|
||||
# quick shorthand
|
||||
def text_width(text : String, sheet : BMSheet)
|
||||
text.chars.reduce 0 do |width, char|
|
||||
bm_char = sheet[:chars].find! { |c| c[:letter] == char }
|
||||
width + bm_char[:xadvance]
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: kerning
|
||||
def position_text(text : String, sheet : BMSheet)
|
||||
positions = [] of NamedTuple(x: Int32, y: Int32, char: BMChar)
|
||||
|
@ -100,4 +108,72 @@ module Funfriend::FontMan
|
|||
positions: positions,
|
||||
}
|
||||
end
|
||||
|
||||
def get_letter_crop(char : BMChar, sheet : BMSheet)
|
||||
x = (char[:x] / sheet[:common][:scale_w]).to_f32
|
||||
y = (char[:y] / sheet[:common][:scale_h]).to_f32
|
||||
w = (char[:width] / sheet[:common][:scale_w]).to_f32
|
||||
h = (char[:height] / sheet[:common][:scale_h]).to_f32
|
||||
|
||||
return {x, y, w, h}
|
||||
end
|
||||
|
||||
def get_text_mesh(text : String, sheet : BMSheet, offset_x : Int32, offset_y : Int32, width : Int32, height : Int32)
|
||||
vertices = [] of Float32
|
||||
indices = [] of Int32
|
||||
|
||||
position_data = FontMan.position_text(text, sheet)
|
||||
|
||||
i = 0
|
||||
position_data[:positions].each do |letter|
|
||||
char = letter[:char]
|
||||
x, y, w, h = get_letter_crop(char, sheet)
|
||||
|
||||
pos_x = ((letter[:x] + offset_x) / width ).to_f32 * 2 - 1
|
||||
pos_w = (char[:width] / width ).to_f32 * 2
|
||||
pos_y = ((letter[:y] + offset_y) / height).to_f32 * 2 - 1
|
||||
pos_h = (char[:height] / height).to_f32 * 2
|
||||
|
||||
vertices += [
|
||||
# ------ positions ------- texture coordinates
|
||||
pos_x + pos_w, pos_y + pos_h, 0.0f32, x + w, y, # top right
|
||||
pos_x + pos_w, pos_y, 0.0f32, x + w, y + h, # bottom right
|
||||
pos_x, pos_y, 0.0f32, x, y + h, # bottom left
|
||||
pos_x, pos_y + pos_h, 0.0f32, x, y, # top left
|
||||
]
|
||||
|
||||
# Indices used for indexed draw calls. Each is used as an index into the four vertices.
|
||||
indices += [
|
||||
0, 1, 3, # first triangle
|
||||
1, 2, 3 # second triangle
|
||||
].map &.+ (i * 4)
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
vertex_buffer = Buffer.new
|
||||
element_buffer = Buffer.new
|
||||
vertex_array = VertexArray.new
|
||||
|
||||
vertex_array.bind do
|
||||
vertex_buffer.bind(Buffer::Target::Array) do |buffer, target|
|
||||
GL.buffer_data_array(target, vertices, Buffer::UsageHint::StaticDraw)
|
||||
vertex_array.define_attributes do |va|
|
||||
va.attribute(3, DataType::Float, false)
|
||||
va.attribute(2, DataType::Float, false)
|
||||
end
|
||||
end
|
||||
|
||||
# bind the element buffer to GL_ELEMENT_ARRAY_BUFFER
|
||||
element_buffer.bind(Buffer::Target::ElementArray)
|
||||
|
||||
# Send index data to the GPU.
|
||||
GL.buffer_data_array(Buffer::Target::ElementArray, indices, Buffer::UsageHint::StaticDraw)
|
||||
end
|
||||
|
||||
# unbind the element buffer.
|
||||
element_buffer.unbind
|
||||
|
||||
return {vertex_array, vertex_buffer}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,14 +53,15 @@ class Funfriend::FunfriendContext < Funfriend::WindowContext
|
|||
|
||||
Funfriend.contexts.each do |context|
|
||||
if context.is_a?(ChatterContext)
|
||||
context.window.position = {
|
||||
x: context.window.position[:x],
|
||||
y: context.window.position[:y] - 30
|
||||
window = context.window
|
||||
window.position = {
|
||||
x: window.position[:x],
|
||||
y: window.position[:y] - context.window_size[:height] - 10
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
Funfriend.add_context(ChatterContext.new(renderer.catmoding ? "HEWWO INTEWLOPEW" : "HELLO INTERLOPER", {
|
||||
Funfriend.add_context(ChatterContext.new(renderer.catmoding ? "HEWWO INTEWWOPEW" : "HELLO INTERLOPER", {
|
||||
x: window.position[:x] + WINDOW_SIZE[:width] // 2,
|
||||
y: window.position[:y] + WINDOW_SIZE[:height] // 2 - 70
|
||||
}))
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
class Funfriend::TextRenderer
|
||||
getter text : String
|
||||
getter sheet : FontMan::BMSheet
|
||||
getter width : Int32
|
||||
getter height : Int32
|
||||
|
||||
getter shader_program : Program
|
||||
getter vertex_array : VertexArray
|
||||
getter vertex_buffer : Buffer
|
||||
getter font_texture : Texture
|
||||
getter sheet : FontMan::BMSheet
|
||||
|
||||
def initialize(text : String, sheet : FontMan::BMSheet)
|
||||
def initialize(text : String, sheet : FontMan::BMSheet, width : Int32, height : Int32)
|
||||
@text = text
|
||||
@sheet = sheet
|
||||
@width = width
|
||||
@height = height
|
||||
|
||||
@shader_program = init_shaders
|
||||
@vertex_array, @vertex_buffer = init_buffers
|
||||
@font_texture = init_textures
|
||||
|
@ -24,77 +29,14 @@ class Funfriend::TextRenderer
|
|||
})[:tex]
|
||||
end
|
||||
|
||||
def get_letter_crop(char : FontMan::BMChar)
|
||||
x = (char[:x] / sheet[:common][:scale_w]).to_f32
|
||||
y = (char[:y] / sheet[:common][:scale_h]).to_f32
|
||||
w = (char[:width] / sheet[:common][:scale_w]).to_f32
|
||||
h = (char[:height] / sheet[:common][:scale_h]).to_f32
|
||||
|
||||
return {x, y, w, h}
|
||||
end
|
||||
|
||||
def init_buffers
|
||||
vertices = [] of Float32
|
||||
indices = [] of Int32
|
||||
|
||||
position_data = FontMan.position_text(text, sheet)
|
||||
|
||||
i = 0
|
||||
position_data[:positions].each do |letter|
|
||||
char = letter[:char]
|
||||
x, y, w, h = get_letter_crop(char)
|
||||
|
||||
pos_x = (letter[:x] / position_data[:width]).to_f32 * 2 - 1
|
||||
pos_w = (char[:width] / position_data[:width]).to_f32 * 2
|
||||
pos_y = (letter[:y] / position_data[:height]).to_f32 * 2 - 1
|
||||
pos_h = (char[:height] / position_data[:height]).to_f32 * 2
|
||||
|
||||
vertices += [
|
||||
# ------ positions ------- texture coordinates
|
||||
pos_x + pos_w, pos_y + pos_h, 0.0f32, x + w, y, # top right
|
||||
pos_x + pos_w, pos_y, 0.0f32, x + w, y + h, # bottom right
|
||||
pos_x, pos_y, 0.0f32, x, y + h, # bottom left
|
||||
pos_x, pos_y + pos_h, 0.0f32, x, y, # top left
|
||||
]
|
||||
|
||||
# Indices used for indexed draw calls. Each is used as an index into the four vertices.
|
||||
indices += [
|
||||
0, 1, 3, # first triangle
|
||||
1, 2, 3 # second triangle
|
||||
].map &.+ (i * 4)
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
vertex_buffer = Buffer.new
|
||||
element_buffer = Buffer.new
|
||||
vertex_array = VertexArray.new
|
||||
|
||||
vertex_array.bind do
|
||||
vertex_buffer.bind(Buffer::Target::Array) do |buffer, target|
|
||||
GL.buffer_data_array(target, vertices, Buffer::UsageHint::StaticDraw)
|
||||
vertex_array.define_attributes do |va|
|
||||
va.attribute(3, DataType::Float, false)
|
||||
va.attribute(2, DataType::Float, false)
|
||||
end
|
||||
end
|
||||
|
||||
# bind the element buffer to GL_ELEMENT_ARRAY_BUFFER
|
||||
element_buffer.bind(Buffer::Target::ElementArray)
|
||||
|
||||
# Send index data to the GPU.
|
||||
GL.buffer_data_array(Buffer::Target::ElementArray, indices, Buffer::UsageHint::StaticDraw)
|
||||
end
|
||||
|
||||
# unbind the element buffer.
|
||||
element_buffer.unbind
|
||||
|
||||
return {vertex_array, vertex_buffer}
|
||||
text_width, text_height = FontMan.text_width(text, sheet), sheet[:common][:line_height]
|
||||
FontMan.get_text_mesh(text, sheet, width // 2 - text_width // 2, height // 2 - text_height // 2, width, height)
|
||||
end
|
||||
|
||||
def init_shaders
|
||||
vertex_shader_source = File.read "src/glsl/nop.vert"
|
||||
fragment_shader_source = File.read "src/glsl/font.frag"
|
||||
fragment_shader_source = File.read "src/glsl/bake_alpha.frag"
|
||||
|
||||
vertex_shader = VertexShader.create(vertex_shader_source)
|
||||
fragment_shader = FragmentShader.create(fragment_shader_source)
|
||||
|
@ -103,7 +45,7 @@ class Funfriend::TextRenderer
|
|||
return Program.create(shaders)
|
||||
end
|
||||
|
||||
def render(dt : Float64, window_width : Int32, window_height : Int32)
|
||||
def render(dt : Float64)
|
||||
font_texture.bind(Texture::Target::Texture2D) do
|
||||
shader_program.use do |p|
|
||||
p.set_uniform("texture1", 0)
|
||||
|
|
Loading…
Reference in New Issue