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"
|
import "vendor:sdl3"
|
||||||
|
|
||||||
State :: struct {
|
State :: struct {
|
||||||
tick: u32,
|
tick: u32,
|
||||||
window: ^sdl3.Window,
|
window: ^sdl3.Window,
|
||||||
program: u32,
|
program: u32,
|
||||||
rect_vao: VAO,
|
rect_vao: VAO,
|
||||||
wireframe: bool,
|
circle_vao: VAO,
|
||||||
|
wireframe: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// {{{ Initialization
|
||||||
init :: proc() -> (state: State, ok: bool) {
|
init :: proc() -> (state: State, ok: bool) {
|
||||||
GL_MAJOR :: 3
|
GL_MAJOR :: 3
|
||||||
GL_MINOR :: 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.load_up_to(GL_MAJOR, GL_MINOR, sdl3.gl_set_proc_address)
|
||||||
OpenGL.ClearColor(0, 0, 0, 1)
|
OpenGL.ClearColor(0, 0, 0, 1)
|
||||||
OpenGL.Enable(OpenGL.DEPTH_TEST)
|
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(
|
state.program = OpenGL.load_shaders_source(
|
||||||
#load("./vert.glsl"),
|
#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
|
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()
|
init_command_queue()
|
||||||
|
|
||||||
return state, true
|
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) {
|
render :: proc(state: ^State) {
|
||||||
state.tick += 1
|
state.tick += 1
|
||||||
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT)
|
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT | OpenGL.DEPTH_BUFFER_BIT)
|
||||||
|
@ -131,20 +159,22 @@ render :: proc(state: ^State) {
|
||||||
2 /
|
2 /
|
||||||
ℝ(count) -
|
ℝ(count) -
|
||||||
1
|
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)
|
render_queue(state)
|
||||||
}
|
}
|
||||||
|
// }}}
|
||||||
close :: proc(state: State) {
|
// {{{ Main
|
||||||
OpenGL.DeleteProgram(state.program)
|
|
||||||
_ = sdl3.StopTextInput(state.window)
|
|
||||||
sdl3.DestroyWindow(state.window)
|
|
||||||
sdl3.Quit()
|
|
||||||
}
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
log.Level_Headers = {
|
log.Level_Headers = {
|
||||||
0 ..< 10 = "[DEBUG] ",
|
0 ..< 10 = "[DEBUG] ",
|
||||||
|
@ -186,3 +216,4 @@ main :: proc() {
|
||||||
free_all(context.temp_allocator)
|
free_all(context.temp_allocator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// }}}
|
||||||
|
|
|
@ -12,25 +12,25 @@ Mat3 :: matrix[3, 3]ℝ
|
||||||
Color :: [4]ℝ
|
Color :: [4]ℝ
|
||||||
// }}}
|
// }}}
|
||||||
// {{{ Command queues
|
// {{{ Command queues
|
||||||
|
Shape :: struct {
|
||||||
|
z: ℝ,
|
||||||
|
fill: Color,
|
||||||
|
}
|
||||||
Rect :: struct {
|
Rect :: struct {
|
||||||
top_left: ℝ²,
|
using shape: Shape,
|
||||||
dimensions: ℝ²,
|
top_left: ℝ²,
|
||||||
z: ℝ,
|
dimensions: ℝ²,
|
||||||
fill: Color,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Circle :: struct {
|
Circle :: struct {
|
||||||
center: ℝ²,
|
using shape: Shape,
|
||||||
radius: ℝ,
|
center: ℝ²,
|
||||||
}
|
radius: ℝ,
|
||||||
|
|
||||||
Shape :: union {
|
|
||||||
Rect,
|
|
||||||
Circle,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Command_Queue :: struct {
|
Command_Queue :: struct {
|
||||||
rects: [dynamic]Rect,
|
rects: [dynamic]Rect,
|
||||||
|
circles: [dynamic]Circle,
|
||||||
}
|
}
|
||||||
|
|
||||||
queue: ^Command_Queue
|
queue: ^Command_Queue
|
||||||
|
@ -43,7 +43,9 @@ init_command_queue :: proc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_rect_args :: proc(top_left: ℝ², dimensions: ℝ², color: Color, z: ℝ = 0) {
|
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) {
|
draw_rect_struct :: proc(rect: Rect) {
|
||||||
|
@ -51,10 +53,24 @@ draw_rect_struct :: proc(rect: Rect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_rect :: proc {
|
draw_rect :: proc {
|
||||||
draw_rect_args,
|
|
||||||
draw_rect_struct,
|
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
|
// {{{ VAO & consts
|
||||||
|
@ -167,6 +183,36 @@ set_rect_transforms :: proc(vao: ^VAO, rects: []Rect) -> ℕ {
|
||||||
|
|
||||||
return len(rects)
|
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
|
// {{{ Render the entire queue
|
||||||
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
draw_instances :: proc(vao: VAO, instances: ℕ) {
|
||||||
|
@ -191,5 +237,15 @@ render_queue :: proc(state: ^State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clear(&queue.rects)
|
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