diff --git a/odin/sdl-opengl-rendering/flake.nix b/odin/sdl-opengl-rendering/flake.nix
index ab66b89..4650e01 100644
--- a/odin/sdl-opengl-rendering/flake.nix
+++ b/odin/sdl-opengl-rendering/flake.nix
@@ -55,6 +55,7 @@
         # {{{ Shell
         devShell = pkgs.mkShell rec {
           nativeBuildInputs = [
+            pkgs.pkg-config
             pkgs.entr # File change detection
             pkgs.odin # Compiler
             pkgs.mold # Linker
@@ -76,7 +77,6 @@
             pkgs.xorg.libXinerama
             pkgs.xorg.libXcursor
             pkgs.sdl3
-            raylib
           ];
 
           LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath buildInputs;
diff --git a/odin/sdl-opengl-rendering/src/main.odin b/odin/sdl-opengl-rendering/src/main.odin
index 1369fa8..07c249d 100644
--- a/odin/sdl-opengl-rendering/src/main.odin
+++ b/odin/sdl-opengl-rendering/src/main.odin
@@ -6,181 +6,100 @@ import "vendor:OpenGL"
 import "vendor:sdl3"
 
 State :: struct {
-	window: ^sdl3.Window,
+	window:              ^sdl3.Window,
+	program:             u32,
+	vertex_pos_location: u32,
+	vbo:                 u32,
+	ibo:                 u32,
 }
 
 init :: proc() -> (state: State, ok: bool) {
+	GL_MAJOR :: 3
+	GL_MINOR :: 1
+
 	sdl3.Init(sdl3.InitFlags{.VIDEO}) or_return
-	sdl3.GL_SetAttribute(.CONTEXT_MAJOR_VERSION, 3) or_return
-	sdl3.GL_SetAttribute(.CONTEXT_MINOR_VERSION, 1) 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
 
-	window := sdl3.CreateWindow("SDL visual experiment", 640, 480, {.FULLSCREEN, .OPENGL})
-	(window != nil) or_return
+	state.window = sdl3.CreateWindow("SDL visual experiment", 640, 480, {.FULLSCREEN, .OPENGL})
+	(state.window != nil) or_return
 
-	gl_ctx := sdl3.GL_CreateContext(window)
+	gl_ctx := sdl3.GL_CreateContext(state.window)
 	(gl_ctx != nil) or_return
 
-	// Init GL here
+	OpenGL.load_up_to(GL_MAJOR, GL_MINOR, sdl3.gl_set_proc_address)
 
-	return {window = window}, true
+	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, "LVertexPos2D")
+	(vertex_pos_location != -1) or_return
+	state.vertex_pos_location = u32(vertex_pos_location)
+
+	OpenGL.ClearColor(0, 0, 0, 1)
+
+	// VBO data
+	vertex_data := [?]f32{-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5}
+	vbos: [1]u32
+
+	// IBO data
+	index_data := [?]u32{0, 1, 2, 3}
+	ibos: [1]u32
+
+	//Create VBO
+	OpenGL.GenBuffers(1, auto_cast &vbos)
+	OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, vbos[0])
+	OpenGL.BufferData(OpenGL.ARRAY_BUFFER, 2 * 4 * size_of(f32), &vertex_data, OpenGL.STATIC_DRAW)
+	state.vbo = vbos[0]
+
+	OpenGL.GenBuffers(1, auto_cast &ibos)
+	OpenGL.BindBuffer(OpenGL.ELEMENT_ARRAY_BUFFER, ibos[0])
+	OpenGL.BufferData(
+		OpenGL.ELEMENT_ARRAY_BUFFER,
+		4 * size_of(u32),
+		&index_data,
+		OpenGL.STATIC_DRAW,
+	)
+	state.ibo = ibos[0]
+
+	return state, true
 }
 
-init_gl :: proc() -> (ok: bool) {
-	program_id := OpenGL.load_shaders_source(#load("./vert.glsl"), #load("./frag.glsl")) or_return
-	return true
+render :: proc(state: State) {
+	OpenGL.Clear(OpenGL.COLOR_BUFFER_BIT)
+
+	OpenGL.UseProgram(state.program)
+	defer OpenGL.UseProgram(0)
+
+	OpenGL.EnableVertexAttribArray(state.vertex_pos_location)
+	defer OpenGL.DisableVertexAttribArray(state.vertex_pos_location)
+
+	OpenGL.BindBuffer(OpenGL.ARRAY_BUFFER, state.vbo)
+	OpenGL.VertexAttribPointer(
+		state.vertex_pos_location,
+		2,
+		OpenGL.FLOAT,
+		false,
+		2 * size_of(f32),
+		0,
+	)
+
+	OpenGL.BindBuffer(OpenGL.ELEMENT_ARRAY_BUFFER, state.ibo)
+	OpenGL.DrawElements(OpenGL.TRIANGLE_FAN, 4, OpenGL.UNSIGNED_INT, nil)
 }
 
-// 				//Get vertex attribute location
-// 				gVertexPos2DLocation = glGetAttribLocation( gProgramID, "LVertexPos2D" );
-// 				if( gVertexPos2DLocation == -1 )
-// 				{
-// 					SDL_Log( "LVertexPos2D is not a valid glsl program variable!\n" );
-// 					success = false;
-// 				}
-// 				else
-// 				{
-// 					//Initialize clear color
-// 					glClearColor( 0.f, 0.f, 0.f, 1.f );
-//
-// 					//VBO data
-// 					GLfloat vertexData[] =
-// 					{
-// 						-0.5f, -0.5f,
-// 						 0.5f, -0.5f,
-// 						 0.5f,  0.5f,
-// 						-0.5f,  0.5f
-// 					};
-//
-// 					//IBO data
-// 					GLuint indexData[] = { 0, 1, 2, 3 };
-//
-// 					//Create VBO
-// 					glGenBuffers( 1, &gVBO );
-// 					glBindBuffer( GL_ARRAY_BUFFER, gVBO );
-// 					glBufferData( GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), vertexData, GL_STATIC_DRAW );
-//
-// 					//Create IBO
-// 					glGenBuffers( 1, &gIBO );
-// 					glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO );
-// 					glBufferData( GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLuint), indexData, GL_STATIC_DRAW );
-
-// void render()
-// {
-// 	//Clear color buffer
-// 	glClear( GL_COLOR_BUFFER_BIT );
-//
-// 	//Render quad
-// 	if( gRenderQuad )
-// 	{
-// 		//Bind program
-// 		glUseProgram( gProgramID );
-//
-// 		//Enable vertex position
-// 		glEnableVertexAttribArray( gVertexPos2DLocation );
-//
-// 		//Set vertex data
-// 		glBindBuffer( GL_ARRAY_BUFFER, gVBO );
-// 		glVertexAttribPointer( gVertexPos2DLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL );
-//
-// 		//Set index data and render
-// 		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, gIBO );
-// 		glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL );
-//
-// 		//Disable vertex position
-// 		glDisableVertexAttribArray( gVertexPos2DLocation );
-//
-// 		//Unbind program
-// 		glUseProgram( 0 );
-// 	}
-// }
-
 close :: proc(state: State) {
+	OpenGL.DeleteProgram(state.program)
 	sdl3.DestroyWindow(state.window)
 	sdl3.Quit()
 }
 
-// void close()
-// {
-// 	//Deallocate program
-// 	glDeleteProgram( gProgramID );
-//
-// 	//Destroy window
-// 	SDL_DestroyWindow( gWindow );
-// 	gWindow = NULL;
-//
-// 	//Quit SDL subsystems
-// 	SDL_Quit();
-// }
-//
-// void printProgramLog( GLuint program )
-// {
-// 	//Make sure name is shader
-// 	if( glIsProgram( program ) )
-// 	{
-// 		//Program log length
-// 		int infoLogLength = 0;
-// 		int maxLength = infoLogLength;
-//
-// 		//Get info string length
-// 		glGetProgramiv( program, GL_INFO_LOG_LENGTH, &maxLength );
-//
-// 		//Allocate string
-// 		char* infoLog = new char[ maxLength ];
-//
-// 		//Get info log
-// 		glGetProgramInfoLog( program, maxLength, &infoLogLength, infoLog );
-// 		if( infoLogLength > 0 )
-// 		{
-// 			//Print Log
-// 			SDL_Log( "%s\n", infoLog );
-// 		}
-//
-// 		//Deallocate string
-// 		delete[] infoLog;
-// 	}
-// 	else
-// 	{
-// 		SDL_Log( "Name %d is not a program\n", program );
-// 	}
-// }
-//
-// void printShaderLog( GLuint shader )
-// {
-// 	//Make sure name is shader
-// 	if( glIsShader( shader ) )
-// 	{
-// 		//Shader log length
-// 		int infoLogLength = 0;
-// 		int maxLength = infoLogLength;
-//
-// 		//Get info string length
-// 		glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &maxLength );
-//
-// 		//Allocate string
-// 		char* infoLog = new char[ maxLength ];
-//
-// 		//Get info log
-// 		glGetShaderInfoLog( shader, maxLength, &infoLogLength, infoLog );
-// 		if( infoLogLength > 0 )
-// 		{
-// 			//Print Log
-// 			SDL_Log( "%s\n", infoLog );
-// 		}
-//
-// 		//Deallocate string
-// 		delete[] infoLog;
-// 	}
-// 	else
-// 	{
-// 		SDL_Log( "Name %d is not a shader\n", shader );
-// 	}
-// }
-
-
 main :: proc() {
 	context.logger = log.create_console_logger()
-	log.debug("Starting")
 	state, ok := init()
 	log.assertf(ok, "Got SDL error: %v", sdl3.GetError())
 	defer close(state)
@@ -198,47 +117,11 @@ main :: proc() {
 			}
 		}
 
+		render(state)
 		sdl3.GL_SwapWindow(state.window)
 		sdl3.StopTextInput(state.window) or_break
 	}
 }
-// 		//Event handler
-// 		SDL_Event e;
-//
-// 		//Enable text input
-// 		SDL_StartTextInput( gWindow );
-//
-// 		//While application is running
-// 		while( !quit )
-// 		{
-// 			//Handle events on queue
-// 			while( SDL_PollEvent( &e ) != 0 )
-// 			{
-// 				//User requests quit
-// 				if( e.type == SDL_EVENT_QUIT )
-// 				{
-// 					quit = true;
-// 				}
 // 				//Handle keypress
 // 				else if( e.type == SDL_EVENT_TEXT_INPUT )
-// 				{
 // 					handleKeys( e.text.text[ 0 ] );
-// 				}
-// 			}
-//
-// 			//Render quad
-// 			render();
-//
-// 			//Update screen
-// 			SDL_GL_SwapWindow( gWindow );
-// 		}
-//
-// 		//Disable text input
-// 		SDL_StopTextInput( gWindow );
-// 	}
-//
-// 	//Free resources and close SDL
-// 	close();
-//
-// 	return 0;
-// }