odin(sdl-opengl-rendering): circle rendering & half-broken transparency
This commit is contained in:
parent
b3aad17877
commit
7a2c5c141b
odin/sdl-opengl-rendering/src
|
@ -9,13 +9,15 @@ import "vendor:OpenGL"
|
|||
import "vendor:sdl3"
|
||||
|
||||
State :: struct {
|
||||
tick: u32,
|
||||
window: ^sdl3.Window,
|
||||
program: u32,
|
||||
rect_vao: VAO,
|
||||
wireframe: bool,
|
||||
tick: u32,
|
||||
window: ^sdl3.Window,
|
||||
program: u32,
|
||||
rect_vao: VAO,
|
||||
circle_vao: VAO,
|
||||
wireframe: bool,
|
||||
}
|
||||
|
||||
// {{{ Initialization
|
||||
init :: proc() -> (state: State, ok: bool) {
|
||||
GL_MAJOR :: 3
|
||||
GL_MINOR :: 3
|
||||
|
@ -93,6 +95,8 @@ init :: proc() -> (state: State, ok: bool) {
|
|||
OpenGL.load_up_to(GL_MAJOR, GL_MINOR, sdl3.gl_set_proc_address)
|
||||
OpenGL.ClearColor(0, 0, 0, 1)
|
||||
OpenGL.Enable(OpenGL.DEPTH_TEST)
|
||||
OpenGL.Enable(OpenGL.BLEND)
|
||||
OpenGL.BlendFunc(OpenGL.SRC_ALPHA, OpenGL.ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
state.program = OpenGL.load_shaders_source(
|
||||
#load("./vert.glsl"),
|
||||
|
@ -101,11 +105,35 @@ init :: proc() -> (state: State, ok: bool) {
|
|||
|
||||
state.rect_vao = create_vao({{-1, -1}, {1, -1}, {1, 1}, {-1, 1}}, {0, 1, 2, 3}) or_return
|
||||
|
||||
CIRCLE_POINTS :: 127
|
||||
circle_vertices: [CIRCLE_POINTS + 1]ℝ²
|
||||
circle_indices: [CIRCLE_POINTS + 2]u32
|
||||
|
||||
for i in 0 ..< CIRCLE_POINTS {
|
||||
θ := ℝ(i) * 2 * math.π / CIRCLE_POINTS
|
||||
circle_vertices[i + 1] = {math.cos(θ), math.sin(θ)}
|
||||
circle_indices[i + 1] = u32(i + 1)
|
||||
}
|
||||
|
||||
circle_indices[CIRCLE_POINTS + 1] = circle_indices[1]
|
||||
|
||||
state.circle_vao = create_vao(circle_vertices[:], circle_indices[:]) or_return
|
||||
|
||||
init_command_queue()
|
||||
|
||||
return state, true
|
||||
}
|
||||
// }}}
|
||||
// {{{ Close
|
||||
close :: proc(state: State) {
|
||||
OpenGL.DeleteProgram(state.program)
|
||||
_ = sdl3.StopTextInput(state.window)
|
||||
sdl3.DestroyWindow(state.window)
|
||||
sdl3.Quit()
|
||||
}
|
||||
// }}}
|
||||
|
||||
// {{{ Render
|
||||
render :: proc(state: ^State) {
|
||||
state.tick += 1
|
||||
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT)
|
||||
|
@ -131,20 +159,22 @@ render :: proc(state: ^State) {
|
|||
2 /
|
||||
ℝ(count) -
|
||||
1
|
||||
draw_rect(Rect{pos, 1 / ℝ(count), 0, {(pos.x + 1) / 2, (pos.y + 1) / 2, 1, 1}})
|
||||
color := Color{(pos.x + 1) / 2, (pos.y + 1) / 2, 1, 1}
|
||||
|
||||
if x > y {
|
||||
draw_rect(pos, 1 / ℝ(count), color)
|
||||
} else {
|
||||
r := 1 / ℝ(count) / 2
|
||||
draw_circle(pos + r, r, color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_circle({-0.25, -0.3}, 0.6, Color{0, 0, 0.5, 0.75}, z = -0.1)
|
||||
render_queue(state)
|
||||
}
|
||||
|
||||
close :: proc(state: State) {
|
||||
OpenGL.DeleteProgram(state.program)
|
||||
_ = sdl3.StopTextInput(state.window)
|
||||
sdl3.DestroyWindow(state.window)
|
||||
sdl3.Quit()
|
||||
}
|
||||
|
||||
// }}}
|
||||
// {{{ Main
|
||||
main :: proc() {
|
||||
log.Level_Headers = {
|
||||
0 ..< 10 = "[DEBUG] ",
|
||||
|
@ -186,3 +216,4 @@ main :: proc() {
|
|||
free_all(context.temp_allocator)
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
|
|
@ -12,25 +12,25 @@ Mat3 :: matrix[3, 3]ℝ
|
|||
Color :: [4]ℝ
|
||||
// }}}
|
||||
// {{{ Command queues
|
||||
Shape :: struct {
|
||||
z: ℝ,
|
||||
fill: Color,
|
||||
}
|
||||
Rect :: struct {
|
||||
top_left: ℝ²,
|
||||
dimensions: ℝ²,
|
||||
z: ℝ,
|
||||
fill: Color,
|
||||
using shape: Shape,
|
||||
top_left: ℝ²,
|
||||
dimensions: ℝ²,
|
||||
}
|
||||
|
||||
Circle :: struct {
|
||||
center: ℝ²,
|
||||
radius: ℝ,
|
||||
}
|
||||
|
||||
Shape :: union {
|
||||
Rect,
|
||||
Circle,
|
||||
using shape: Shape,
|
||||
center: ℝ²,
|
||||
radius: ℝ,
|
||||
}
|
||||
|
||||
Command_Queue :: struct {
|
||||
rects: [dynamic]Rect,
|
||||
rects: [dynamic]Rect,
|
||||
circles: [dynamic]Circle,
|
||||
}
|
||||
|
||||
queue: ^Command_Queue
|
||||
|
@ -43,7 +43,9 @@ init_command_queue :: proc() {
|
|||
}
|
||||
|
||||
draw_rect_args :: proc(top_left: ℝ², dimensions: ℝ², color: Color, z: ℝ = 0) {
|
||||
draw_rect_struct(Rect{top_left, dimensions, z, color})
|
||||
draw_rect_struct(
|
||||
Rect{top_left = top_left, dimensions = dimensions, shape = Shape{z = z, fill = color}},
|
||||
)
|
||||
}
|
||||
|
||||
draw_rect_struct :: proc(rect: Rect) {
|
||||
|
@ -51,10 +53,24 @@ draw_rect_struct :: proc(rect: Rect) {
|
|||
}
|
||||
|
||||
draw_rect :: proc {
|
||||
draw_rect_args,
|
||||
draw_rect_struct,
|
||||
draw_rect_args,
|
||||
}
|
||||
|
||||
draw_circle_args :: proc(center: ℝ², radius: ℝ, color: Color, z: ℝ = 0) {
|
||||
draw_circle_struct(
|
||||
Circle{center = center, radius = radius, shape = Shape{z = z, fill = color}},
|
||||
)
|
||||
}
|
||||
|
||||
draw_circle_struct :: proc(circle: Circle) {
|
||||
append(&queue.circles, circle)
|
||||
}
|
||||
|
||||
draw_circle :: proc {
|
||||
draw_circle_struct,
|
||||
draw_circle_args,
|
||||
}
|
||||
// }}}
|
||||
|
||||
// {{{ VAO & consts
|
||||
|
@ -167,6 +183,36 @@ set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
|||
|
||||
return len(rects)
|
||||
}
|
||||
|
||||
set_circle_transforms :: proc(vao: ^VAO, circles: []Circle) -> ℕ {
|
||||
log.assert(len(circles) <= INSTANCES, "Attempting to send too many circles to the GPU")
|
||||
matrices := new([INSTANCES]Mat3, context.temp_allocator)
|
||||
fills := new([INSTANCES]Color, context.temp_allocator)
|
||||
|
||||
for circle, i in circles {
|
||||
mat: Mat3
|
||||
|
||||
mat[0, 0] = circle.radius
|
||||
mat[1, 1] = circle.radius
|
||||
mat[2].xy = circle.center.xy
|
||||
mat[2].z = circle.z
|
||||
|
||||
matrices[i] = mat
|
||||
fills[i] = circle.fill
|
||||
}
|
||||
|
||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_mat_buffer)
|
||||
OpenGL.BufferData(
|
||||
OpenGL.ARRAY_BUFFER,
|
||||
INSTANCES * size_of(Mat3),
|
||||
matrices,
|
||||
OpenGL.DYNAMIC_DRAW,
|
||||
)
|
||||
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vao.instance_fill_buffer)
|
||||
OpenGL.BufferData(OpenGL.ARRAY_BUFFER, INSTANCES * size_of(Color), fills, OpenGL.DYNAMIC_DRAW)
|
||||
|
||||
return len(circles)
|
||||
}
|
||||
// }}}
|
||||
// {{{ Render the entire queue
|
||||
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
||||
|
@ -191,5 +237,15 @@ render_queue :: proc(state: ^State) {
|
|||
}
|
||||
|
||||
clear(&queue.rects)
|
||||
circle_steps := len(queue.circles) / INSTANCES
|
||||
|
||||
for i := 0; i < len(queue.circles); i += INSTANCES {
|
||||
slice := queue.circles[i:]
|
||||
if len(slice) > INSTANCES {slice = slice[:INSTANCES]}
|
||||
instances := set_circle_transforms(&state.circle_vao, slice)
|
||||
draw_instances(state.circle_vao, instances)
|
||||
}
|
||||
|
||||
clear(&queue.circles)
|
||||
}
|
||||
// }}}
|
||||
|
|
Loading…
Reference in a new issue