1
Fork 0
solar-conflux/odin/sdl-opengl-rendering/src/main.odin

205 lines
4.5 KiB
Odin

package visuals
import "base:runtime"
import "core:c"
import "core:fmt"
import "core:log"
import "vendor:OpenGL"
import "vendor:sdl3"
State :: struct {
window: ^sdl3.Window,
program: u32,
vertex_pos_location: u32,
vao: u32,
vbo: u32,
ibo: u32,
wireframe: bool,
}
init :: proc() -> (state: State, ok: bool) {
GL_MAJOR :: 3
GL_MINOR :: 3
// {{{ Configure logging
@(static) g_ctx: runtime.Context
g_ctx = context
sdl3.SetLogPriorities(.VERBOSE)
sdl3.SetLogOutputFunction(
proc "c" (
userdata: rawptr,
category: sdl3.LogCategory,
priority: sdl3.LogPriority,
message: cstring,
) {
context = g_ctx
level: log.Level
switch priority {
case .TRACE, .DEBUG, .VERBOSE:
level = .Debug
case .INFO:
level = .Info
case .WARN:
level = .Warning
case .ERROR:
level = .Error
case .CRITICAL:
level = .Fatal
case .INVALID:
fallthrough
case:
log.panicf("Unexpected log level %v", priority)
}
options: runtime.Logger_Options =
context.logger.options - {.Short_File_Path, .Long_File_Path, .Procedure, .Line}
context.logger.procedure(
context.logger.data,
level,
fmt.tprintf("[SDL/%v]: %v", category, message),
options,
)
},
nil,
)
// }}}
sdl3.Init(sdl3.InitFlags{.VIDEO}) or_return
sdl3.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, GL_MAJOR) or_return
sdl3.GL_SetAttribute(.CONTEXT_MINOR_VERSION, GL_MINOR) or_return
sdl3.GL_SetAttribute(.CONTEXT_PROFILE_MASK, c.int(sdl3.GL_CONTEXT_PROFILE_CORE)) or_return
sdl3.GL_SetSwapInterval(1) // vsync
state.window = sdl3.CreateWindow(
"SDL visual experiment",
640,
480,
{.FULLSCREEN, .OPENGL, .RESIZABLE},
)
(state.window != nil) or_return
sdl3.StartTextInput(state.window) or_return
gl_ctx := sdl3.GL_CreateContext(state.window)
(gl_ctx != nil) or_return
OpenGL.load_up_to(GL_MAJOR, GL_MINOR, sdl3.gl_set_proc_address)
state.program = OpenGL.load_shaders_source(
#load("./vert.glsl"),
#load("./frag.glsl"),
) or_return
// log.debug("Doing Opengl stuff")
vertex_pos_location := OpenGL.GetAttribLocation(state.program, "aPos")
(vertex_pos_location != -1) or_return
state.vertex_pos_location = u32(vertex_pos_location)
OpenGL.ClearColor(0, 0, 0, 1)
// VBO data
vertex_data := 2 * [?]f32{-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5}
// IBO data
index_data := [?]u32{0, 1, 2, 3}
OpenGL.GenVertexArrays(1, &state.vao)
OpenGL.BindVertexArray(state.vao)
//Create VBO
OpenGL.GenBuffers(1, &state.vbo)
OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, state.vbo)
OpenGL.BufferData(OpenGL.ARRAY_BUFFER, 2 * 4 * size_of(f32), &vertex_data, OpenGL.STATIC_DRAW)
OpenGL.EnableVertexAttribArray(state.vertex_pos_location)
OpenGL.VertexAttribPointer(
state.vertex_pos_location,
2,
OpenGL.FLOAT,
false,
2 * size_of(f32),
0,
)
OpenGL.GenBuffers(1, auto_cast &state.ibo)
OpenGL.BindBuffer(OpenGL.ELEMENT_ARRAY_BUFFER, state.ibo)
OpenGL.BufferData(
OpenGL.ELEMENT_ARRAY_BUFFER,
4 * size_of(u32),
&index_data,
OpenGL.STATIC_DRAW,
)
OpenGL.BindVertexArray(0)
OpenGL.DisableVertexAttribArray(state.vertex_pos_location)
return state, true
}
render :: proc(state: State) {
OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT)
OpenGL.UseProgram(state.program)
defer OpenGL.UseProgram(0)
if state.wireframe {
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.LINE)
} else {
OpenGL.PolygonMode(OpenGL.FRONT_AND_BACK, OpenGL.FILL)
}
OpenGL.BindVertexArray(state.vao)
OpenGL.DrawElements(OpenGL.TRIANGLE_FAN, 4, OpenGL.UNSIGNED_INT, nil)
}
close :: proc(state: State) {
OpenGL.DeleteProgram(state.program)
_ = sdl3.StopTextInput(state.window)
sdl3.DestroyWindow(state.window)
sdl3.Quit()
}
main :: proc() {
log.Level_Headers = {
0 ..< 10 = "[DEBUG] ",
10 ..< 20 = "[INFO ] ",
20 ..< 30 = "[WARN ] ",
30 ..< 40 = "[ERROR] ",
40 ..< 50 = "[FATAL] ",
}
logger := log.create_console_logger()
logger.options -= {.Date, .Time}
context.logger = logger
state, ok := init()
log.assertf(ok, "Got SDL error: %v", sdl3.GetError())
defer close(state)
quit := false
for !quit {
event: sdl3.Event
for sdl3.PollEvent(&event) {
#partial switch event.type {
case .WINDOW_RESIZED:
OpenGL.Viewport(0, 0, event.window.data1, event.window.data2)
case .QUIT:
quit = true
case .TEXT_INPUT:
switch ([^]u8)(event.text.text)[0] {
case 'w':
state.wireframe = !state.wireframe
}
log.debug(event.text)
}
}
render(state)
sdl3.GL_SwapWindow(state.window)
}
}