lateralis/main.odin
2025-02-03 18:15:56 +13:00

158 lines
4 KiB
Odin

package main
import "base:runtime"
import "core:fmt"
import "core:log"
import glm "core:math/linalg/glsl"
import "core:math/rand"
import sapp "sokol/app"
import sg "sokol/gfx"
import sglue "sokol/glue"
import slog "sokol/log"
MAX_QUADS :: 1_000_000
Quad :: struct #packed {
transform: glm.mat4,
color: glm.vec3,
}
ctx: runtime.Context
state: struct {
pip: sg.Pipeline,
bind: sg.Bindings,
pass_action: sg.Pass_Action,
quads: [MAX_QUADS]Quad,
quad_count: uint,
proj: glm.mat4,
}
player_pos: glm.vec2
init :: proc "c" () {
ctx = runtime.default_context()
context = ctx
context.logger = log.create_console_logger()
sg.setup({environment = sglue.environment(), logger = {func = slog.func}})
vertices := [?]glm.vec2{{-0.5, 0.5}, {-0.5, -0.5}, {0.5, -0.5}, {0.5, 0.5}}
indicies := [?]u16{0, 1, 2, 0, 2, 3}
state.bind.vertex_buffers[0] = sg.make_buffer({data = {ptr = &vertices, size = size_of(vertices)}})
state.bind.vertex_buffers[1] = sg.make_buffer({size = MAX_QUADS * size_of(Quad), usage = .STREAM})
state.bind.index_buffer = sg.make_buffer(
{type = .INDEXBUFFER, data = {ptr = &indicies, size = size_of(indicies)}},
)
state.pip = sg.make_pipeline(
{
shader = sg.make_shader(quad_shader_desc(sg.query_backend())),
layout = {
buffers = {1 = {step_func = .PER_INSTANCE}},
attrs = {
ATTR_quad_position = {format = .FLOAT2, buffer_index = 0},
ATTR_quad_inst_mat0 = {format = .FLOAT4, buffer_index = 1},
ATTR_quad_inst_mat1 = {format = .FLOAT4, buffer_index = 1},
ATTR_quad_inst_mat2 = {format = .FLOAT4, buffer_index = 1},
ATTR_quad_inst_mat3 = {format = .FLOAT4, buffer_index = 1},
ATTR_quad_color = {format = .FLOAT3, buffer_index = 1},
},
},
depth = {write_enabled = false},
index_type = .UINT16,
},
)
state.pass_action = {
colors = {0 = {load_action = .CLEAR, clear_value = {r = 0, g = 0, b = 0, a = 1}}},
}
}
draw_quad :: proc(pos, size: glm.vec2, rotation := f32(0), color := glm.vec3(1)) {
model := glm.mat4Translate({pos.x + size.x / 2, pos.y + size.y / 2, 0})
model *= glm.mat4Rotate({0, 0, 1}, glm.radians(rotation))
model *= glm.mat4Scale({size.x, size.y, 0})
mvp := state.proj * model
state.quads[state.quad_count] = {
transform = mvp,
color = color,
}
state.quad_count += 1
}
flush_quads :: proc() {
sg.update_buffer(
state.bind.vertex_buffers[1],
{ptr = &state.quads, size = size_of(Quad) * state.quad_count},
)
sg.begin_pass({action = state.pass_action, swapchain = sglue.swapchain()})
sg.apply_pipeline(state.pip)
sg.apply_bindings(state.bind)
sg.draw(0, 6, state.quad_count)
sg.end_pass()
sg.commit()
state.quad_count = 0
}
frame :: proc "c" () {
context = ctx
state.proj = glm.mat4Ortho3d(0, f32(sapp.width()), f32(sapp.height()), 0, -1, 1)
draw_quad(player_pos, {50, 100}, 0)
flush_quads()
}
event :: proc "c" (event: ^sapp.Event) {
context = ctx
#partial switch event.type {
case .KEY_DOWN:
if event.key_code == .ESCAPE {
sapp.quit()
}
if event.key_code == .W {
player_pos.y -= 10
}
if event.key_code == .S {
player_pos.y += 10
}
if event.key_code == .A {
player_pos.x -= 10
}
if event.key_code == .D {
player_pos.x += 10
}
}
}
cleanup :: proc "c" () {
context = ctx
sg.shutdown()
}
main :: proc() {
sapp.run(
{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
event_cb = event,
width = 640,
height = 480,
window_title = "triangle",
icon = {sokol_default = true},
logger = {func = slog.func},
},
)
}