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; -// }