// // Miminal C++ SDL2 OpenGL 4.5 example // // by Poddubny Michael // // Download OpenGL header: // wget https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h // // Compile: // g++ -std=c++11 sdl2_opengl_4_5_triangle.cpp -I. -lSDL2 -o sdl2_opengl_4_5_triangle #include #include #include extern int main(int argc, char *argv[]) { using namespace std; // initialize SDL2 if (SDL_Init(SDL_INIT_VIDEO) < 0) { cerr << "Error: " << SDL_GetError() << '\n'; return EXIT_FAILURE; } atexit(SDL_Quit); // configs constexpr int gl_major_version = 4; constexpr int gl_minor_version = 5; constexpr bool gl_debug = true; constexpr const char * window_title = "OpenGL 4.5 + SDL2 Basic window"; constexpr int window_width = 1024; constexpr int window_height = 768; constexpr bool fullscreen = false; constexpr bool vsync = false; // window without borders and show immediately const auto window_flags = SDL_WINDOW_BORDERLESS | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (fullscreen ? SDL_WINDOW_FULLSCREEN : 0); // opengl forawrd debug context flags const auto context_flags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG | (gl_debug ? SDL_GL_CONTEXT_DEBUG_FLAG : 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, gl_major_version); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, gl_minor_version); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, context_flags); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // create centered window auto window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, window_flags); if (!window) { cerr << "Error: " << SDL_GetError() << '\n'; return EXIT_FAILURE; } // create opengl context auto context = SDL_GL_CreateContext(window); if (!context) { cerr << "Error: " << SDL_GetError() << '\n'; return EXIT_FAILURE; } if (vsync) SDL_GL_SetSwapInterval(1); // load opengl library if (SDL_GL_LoadLibrary(NULL) != 0) { cerr << "Error: " << SDL_GetError() << '\n'; return EXIT_FAILURE; } // get functions PFNGLCLIPCONTROLPROC glClipControl = (PFNGLCLIPCONTROLPROC)SDL_GL_GetProcAddress("glClipControl"); PFNGLVIEWPORTINDEXEDFPROC glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC)SDL_GL_GetProcAddress("glViewportIndexedf"); PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)SDL_GL_GetProcAddress("glClearNamedFramebufferfv"); PFNGLCREATEBUFFERSPROC glCreateBuffers = (PFNGLCREATEBUFFERSPROC)SDL_GL_GetProcAddress("glCreateBuffers"); PFNGLNAMEDBUFFERDATAPROC glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC)SDL_GL_GetProcAddress("glNamedBufferData"); PFNGLCREATEVERTEXARRAYSPROC glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glCreateVertexArrays"); PFNGLENABLEVERTEXARRAYATTRIBPROC glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC)SDL_GL_GetProcAddress("glEnableVertexArrayAttrib"); PFNGLVERTEXARRAYATTRIBFORMATPROC glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC)SDL_GL_GetProcAddress("glVertexArrayAttribFormat"); PFNGLVERTEXARRAYVERTEXBUFFERPROC glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC)SDL_GL_GetProcAddress("glVertexArrayVertexBuffer"); PFNGLBINDVERTEXARRAYPROC glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)SDL_GL_GetProcAddress("glBindVertexArray"); PFNGLDRAWARRAYSPROC glDrawArrays = (PFNGLDRAWARRAYSPROC)SDL_GL_GetProcAddress("glDrawArrays"); SDL_GL_UnloadLibrary(); bool running = true; const float points[] = { // vertices of triangle 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f }; GLuint vbo; // vertex buffer GLuint vao; // vertex array // Create VBO glCreateBuffers(1, &vbo); // Allocate memory for data and send it glNamedBufferData(vbo, sizeof (points), points, GL_STATIC_DRAW); // Create VAO glCreateVertexArrays(1, &vao); // Enable vertex attribute (location = 0) glEnableVertexArrayAttrib(vao, 0); // Setup vertex array attributes glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0); // Setup vertex buffer for this VAO glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(float) * 3); glBindVertexArray(vao); while (running) { SDL_Event ev; while (SDL_PollEvent(&ev)) { if (ev.key.keysym.sym == SDLK_ESCAPE) running = false; // Exit when esc } const float clear_color[4] = {0.4, 0.4, 0.4, 1}; // Clip window glClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE); // Setup viewport 0 glViewportIndexedf(0, 0, 0, (float)window_width , (float)window_height); // Clear color buffer of current framebuffer(0) glClearNamedFramebufferfv(0, GL_COLOR, 0, clear_color); // Draw triangle glDrawArrays(GL_TRIANGLES, 0, 3); SDL_GL_SwapWindow(window); } return 0; }