funfriend/src/funfriend_renderer.cr

118 lines
3.6 KiB
Crystal

class Funfriend::FunfriendRenderer
FPS = 10.0
getter shader_program : Program
getter vertex_array : VertexArray
getter vertex_buffer : Buffer
getter textures : Hash(String, TextureMan::TextureBasket)
property catmoding : Bool
def initialize
@catmoding = false
@shader_program = init_shaders
@vertex_array, @vertex_buffer = init_buffers
@textures = init_textures
end
def funfriend_size
funfriend_size = ConfigMan.config["window"]["funfriend_size"].as(Int32)
{width: funfriend_size, height: funfriend_size}
end
def init_textures
return {
"normal" => TextureMan::TextureBasket.new(
(0..39).map { |i| TextureMan.load_texture("assets/funfriend/funfriend_#{i.to_s.rjust(2, '0')}.png") },
FPS
),
"cat" => TextureMan::TextureBasket.new(
(0..39).map { |i| TextureMan.load_texture("assets/funfriend/catfriend_#{i.to_s.rjust(2, '0')}.png") },
FPS
)
}
end
def init_buffers
vertices = {
# ------ positions ------- texture coordinates
1.0f32, 1.0f32, 0.0f32, 1.0f32, 1.0f32, # top right
1.0f32, -1.0f32, 0.0f32, 1.0f32, 0.0f32, # bottom right
-1.0f32, -1.0f32, 0.0f32, 0.0f32, 0.0f32, # bottom left
-1.0f32, 1.0f32, 0.0f32, 0.0f32, 1.0f32 # 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
}
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|
target.buffer_data(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.
Buffer::Target::ElementArray.buffer_data(indices, Buffer::UsageHint::StaticDraw)
end
# unbind the element buffer.
element_buffer.unbind
return {vertex_array, vertex_buffer}
end
def init_shaders
vertex_shader_source = FileStorage.get("nop.vert").gets_to_end
fragment_shader_source = FileStorage.get("funfriend.frag").gets_to_end
vertex_shader = VertexShader.create(vertex_shader_source)
fragment_shader = FragmentShader.create(fragment_shader_source)
shaders = {vertex_shader, fragment_shader}
return Program.create(shaders)
end
def render(dt : Float64, window_width : Int32, window_height : Int32)
LibGL.clear_color(0.0, 0.0, 0.0, 0.0)
LibGL.clear(Buffer::Bit::Color)
textures.each_value &.update(dt)
texture_basket = textures[catmoding ? "cat" : "normal"]
frame = texture_basket.texture
width, height = frame[:width], frame[:height]
Texture::Unit.activate(0)
frame[:tex].bind(Texture::Target::Texture2D) do
shader_program.use do |shader|
shader.set_uniform("texture1", 0)
shader.set_uniform("funfriendSize", funfriend_size[:width].to_f32, funfriend_size[:height].to_f32)
shader.set_uniform("resolution", window_width.to_f32, window_height.to_f32)
shader.set_uniform("time", CrystGLFW.time.to_f32)
vertex_array.bind do
LibGL.draw_elements(LibGL::TRIANGLES, 6, DataType::UnsignedInt, Pointer(Void).new(0))
end
end
end
end
def clean_up
{vertex_array, vertex_buffer}.each { |v| v.delete }
end
end