Glenn Yonemitsu - software engineer. yonemitsu@gmail.com

Starting OpenGL in SDL3

This is just a quick shortcut guide to get Open GL started in Odin/SDL3.

Writing shaders is absolutely not in scope here.

package main

import "core:fmt"
import gl "vendor:OpenGL"
import sdl "vendor:sdl3"

GL_VERSION_MAJOR :: 4
GL_VERSION_MINOR :: 1

main :: proc() {
	success := sdl.Init({.AUDIO, .VIDEO, .EVENTS})
	if !success {
		fmt.eprintf("Failed to init SDL: %s\n", sdl.GetError())
		return
	}
	defer sdl.Quit()

	sdl.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, GL_VERSION_MAJOR)
	sdl.GL_SetAttribute(.CONTEXT_MINOR_VERSION, GL_VERSION_MINOR)
	sdl.GL_SetAttribute(.CONTEXT_PROFILE_MASK, i32(sdl.GL_CONTEXT_PROFILE_CORE))

	window := sdl.CreateWindow("my game", 800, 600, {.OPENGL})
	if window == nil {
		fmt.eprintf("Error creating window: %s\n", sdl.GetError())
		return
	}
	defer sdl.DestroyWindow(window)

	glctx := sdl.GL_CreateContext(window)
	if glctx == nil {
		fmt.eprintf("Cannot create OpenGL context: %s\n", sdl.GetError())
		return
	}
	defer sdl.GL_DestroyContext(glctx)

	gl.load_up_to(GL_VERSION_MAJOR, GL_VERSION_MINOR, sdl.gl_set_proc_address)

	// Rest of the game here
}

Breakdown

Obvious SDL initialization

success := sdl.Init({.AUDIO, .VIDEO, .EVENTS})

Obviously needed to get SDL started.

References: SDL_Init

Setting up OpenGL attributes and making the window

sdl.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, GL_VERSION_MAJOR)
sdl.GL_SetAttribute(.CONTEXT_MINOR_VERSION, GL_VERSION_MINOR)
sdl.GL_SetAttribute(.CONTEXT_PROFILE_MASK, i32(sdl.GL_CONTEXT_PROFILE_CORE))
window := sdl.CreateWindow("my game", 800, 600, {.OPENGL})

Setting OpenGL attributes for a window. Here if your app is going to have multiple windows, this is how you can set different OpenGL attributes per window. Probably going to be very rare, but possible.

Unless there is a specific need to do so, there is no need to explicitly call sdl.GL_LoadLibrary.

References: SDL_GL_SetAttribute, SDL_GLAttr enum definition, SDL_GL_LoadLibrary.

Creating the OpenGL context

glctx := sdl.GL_CreateContext(window)

Create the OpenGL context and make it the default.

OpenGL is a stateful API, so if you were to make multiple windows with different contexts and need to switch between then, you need to call sdl.GL_MakeCurrent.

If only one context is used (which would be the majority of cases) then sdl.GL_MakeCurrent does not need to be called.

References: SDL_GL_CreateContext, SDL_GL_MakeCurrent

Load up the driver code (?)

gl.load_up_to(GL_VERSION_MAJOR, GL_VERSION_MINOR, sdl.gl_set_proc_address)

Tells OpenGL what API to load into the runtime.

I'll be honest I'm not 100% sure why this is needed, but it is.

At this point you are ready to do some OpenGL and shader programming!