146 lines
4.0 KiB
Odin
146 lines
4.0 KiB
Odin
package render
|
|
|
|
import rl "libs:raylib"
|
|
import gl "vendor:OpenGL"
|
|
|
|
MAX_VERTICES :: 4096
|
|
MAX_INDICES :: 4096
|
|
MAX_DRAWS :: 4096
|
|
|
|
Vec3 :: [3]f32
|
|
|
|
Draw_Call :: struct {
|
|
color: rl.Color,
|
|
first_index, num_indices: i32,
|
|
base_vertex: i32,
|
|
}
|
|
|
|
Immediate_Buffer :: enum {
|
|
Vertices = 0,
|
|
Indices,
|
|
}
|
|
|
|
Immediate_Draw_State :: struct {
|
|
vertices: [MAX_VERTICES]Vec3,
|
|
indices: [MAX_INDICES]u16,
|
|
draws: [MAX_DRAWS]Draw_Call,
|
|
num_vertices, num_indices, num_draws: int,
|
|
vbo_ids: [Immediate_Buffer]u32,
|
|
vao_id: u32,
|
|
}
|
|
|
|
push_mesh :: proc(ds: ^Immediate_Draw_State, vertices: []Vec3, indices: []u16, color: rl.Color) {
|
|
copy(ds.vertices[ds.num_vertices:][:len(vertices)], vertices)
|
|
copy(ds.indices[ds.num_indices:][:len(indices)], indices)
|
|
ds.draws[ds.num_draws] = {
|
|
color = color,
|
|
first_index = i32(ds.num_indices),
|
|
num_indices = i32(len(indices)),
|
|
base_vertex = i32(ds.num_vertices),
|
|
}
|
|
ds.num_vertices += len(vertices)
|
|
ds.num_indices += len(indices)
|
|
ds.num_draws += 1
|
|
}
|
|
|
|
// rudimentary batching
|
|
find_or_push_cmd :: proc(ds: ^Immediate_Draw_State, color: rl.Color) -> (cmd: ^Draw_Call) {
|
|
if ds.num_draws > 0 && ds.draws[ds.num_draws - 1].color == color {
|
|
cmd = &ds.draws[ds.num_draws - 1]
|
|
assert(i32(ds.num_indices) == cmd.first_index + cmd.num_indices)
|
|
} else {
|
|
ds.draws[ds.num_draws] = {
|
|
color = color,
|
|
first_index = i32(ds.num_indices),
|
|
num_indices = 0,
|
|
base_vertex = i32(ds.num_vertices),
|
|
}
|
|
cmd = &ds.draws[ds.num_draws]
|
|
ds.num_draws += 1
|
|
}
|
|
return
|
|
}
|
|
|
|
push_tri :: proc(ds: ^Immediate_Draw_State, v1, v2, v3: Vec3, color: rl.Color) {
|
|
draw := find_or_push_cmd(ds, color)
|
|
|
|
ds.vertices[ds.num_vertices + 0] = v1
|
|
ds.vertices[ds.num_vertices + 1] = v2
|
|
ds.vertices[ds.num_vertices + 2] = v3
|
|
ds.indices[ds.num_indices + 0] = u16(ds.num_vertices + 0)
|
|
ds.indices[ds.num_indices + 1] = u16(ds.num_vertices + 1)
|
|
ds.indices[ds.num_indices + 2] = u16(ds.num_vertices + 2)
|
|
ds.num_vertices += 3
|
|
ds.num_indices += 3
|
|
draw.num_indices += 3
|
|
}
|
|
|
|
push_quad :: proc(ds: ^Immediate_Draw_State, v1, v2, v3, v4: Vec3, color: rl.Color) {
|
|
push_tri(ds, v1, v2, v3, color)
|
|
push_tri(ds, v1, v3, v4, color)
|
|
}
|
|
|
|
draw_batch :: proc(ds: ^Immediate_Draw_State) {
|
|
if ds.vbo_ids == {} {
|
|
gl.GenBuffers(len(ds.vbo_ids), &ds.vbo_ids[.Vertices])
|
|
gl.GenVertexArrays(1, &ds.vao_id)
|
|
|
|
gl.BindVertexArray(ds.vao_id)
|
|
gl.EnableVertexAttribArray(u32(rl.ShaderLocationIndex.VERTEX_POSITION))
|
|
|
|
gl.BindBuffer(gl.ARRAY_BUFFER, ds.vbo_ids[.Vertices])
|
|
gl.VertexAttribPointer(
|
|
u32(rl.ShaderLocationIndex.VERTEX_POSITION),
|
|
3,
|
|
gl.FLOAT,
|
|
false,
|
|
0,
|
|
0,
|
|
)
|
|
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ds.vbo_ids[.Indices])
|
|
|
|
} else {
|
|
gl.BindVertexArray(ds.vao_id)
|
|
}
|
|
gl.BindVertexArray(0)
|
|
|
|
defer gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
|
|
|
gl.BufferData(gl.ARRAY_BUFFER, MAX_VERTICES * size_of(Vec3), nil, gl.STREAM_DRAW)
|
|
gl.BufferSubData(gl.ARRAY_BUFFER, 0, ds.num_vertices * size_of(Vec3), raw_data(ds.vertices[:]))
|
|
gl.VertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0)
|
|
gl.EnableVertexAttribArray(0)
|
|
defer gl.DisableVertexAttribArray(0)
|
|
|
|
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, ds.vbo_ids[.Indices])
|
|
defer gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
|
|
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, MAX_INDICES * size_of(u16), nil, gl.STREAM_DRAW)
|
|
gl.BufferSubData(
|
|
gl.ELEMENT_ARRAY_BUFFER,
|
|
0,
|
|
ds.num_indices * size_of(u16),
|
|
raw_data(ds.indices[:]),
|
|
)
|
|
|
|
shader := rl.LoadMaterialDefault().shader
|
|
rl.BeginShaderMode(shader)
|
|
defer rl.EndShaderMode()
|
|
|
|
for draw in ds.draws[:ds.num_draws] {
|
|
color: [4]f32 = {
|
|
f32(draw.color.r) / 255.0,
|
|
f32(draw.color.g) / 255.0,
|
|
f32(draw.color.b) / 255.0,
|
|
f32(draw.color.a) / 255.0,
|
|
}
|
|
gl.Uniform4fv(shader.locs[rl.ShaderLocationIndex.COLOR_DIFFUSE], 1, raw_data(color[:]))
|
|
gl.DrawElementsBaseVertex(
|
|
gl.TRIANGLES,
|
|
i32(ds.num_indices / 3),
|
|
gl.UNSIGNED_SHORT,
|
|
rawptr(uintptr(draw.first_index) * size_of(u16)),
|
|
draw.base_vertex,
|
|
)
|
|
}
|
|
}
|