Dla prostej grafiki stary poczciwy OpenGL byłby w stanie takie coś narysować. Wiem, że teraz jest inny nowocześniejszy styl programowania w OGL z szaderami, ale stary nadal działa i będzie działać. Taki prosty przykład z wykorzystaniem SDL oraz OpenGL w trybie bezpośrednim.
Kopiuj
// g++ -o main main.cpp -std=c++20 -Wall -Wextra `sdl2-config --cflags --libs` -lOpenGL32 -lGLU32 -lm && ./main
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL2/SDL.h>
#include <cmath>
#include <iostream>
#include <numbers>
using std::numbers::pi;
struct vec2 { float x, y; };
struct vec3 { float x, y, z; };
const vec3 orange{0.8, 0.5, 0.0};
const vec3 light{0.8, 0.8, 0.8};
const vec3 dark{0.1, 0.1, 0.1};
constexpr int width = 480;
constexpr int height = 320;
// functions declarations
void initGL();
void setOrigin(const vec3& position);
void drawTriangle(const vec2& v1, const vec2& v2, const vec2& v3, const vec3& color);
void drawQuad(const float width, const float height, const vec3& color);
void drawHexagon(const float radius, const vec3& color);
int main(int, char*[]) {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* ws = SDL_CreateWindow("gra", 50, 50, width, height, SDL_WINDOW_OPENGL);
SDL_GLContext ctx = SDL_GL_CreateContext(ws);
SDL_GL_MakeCurrent(ws, ctx);
initGL();
bool quit = false;
for (;;) {
// process events
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (((event.type == SDL_QUIT) || (event.type == SDL_KEYDOWN)) &&
(event.key.keysym.sym == SDLK_ESCAPE)) {
quit = true;
}
}
if (quit) break;
// clear screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw section
setOrigin({(width / 10.0)*1.5, height - 20, 0});
for (int i = 0; i < 8; i++) {
drawHexagon(10, orange);
glTranslatef(width / 10, 0, 0);
}
setOrigin({width / 2, 20, 0});
drawTriangle({0, 0}, {20, 0}, {10, 20}, light);
setOrigin({40, 100, 0});
drawQuad(100, 50, dark);
// swap buffers
SDL_GL_SwapWindow(ws);
}
SDL_GL_DeleteContext(ctx);
SDL_DestroyWindow(ws);
SDL_Quit();
return 0;
}
void initGL() {
glEnable(GL_DEPTH_TEST);
glClearColor(0.3f, 0.3f, 0.5f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
}
void setOrigin(const vec3& position) {
glLoadIdentity();
glTranslatef(position.x, position.y, position.z);
}
void drawTriangle(const vec2& v1, const vec2& v2, const vec2& v3, const vec3& color) {
glBegin(GL_TRIANGLES);
glColor3fv(&color.x);
glVertex2fv(&v1.x);
glVertex2fv(&v2.x);
glVertex2fv(&v3.x);
glEnd();
}
void drawQuad(const float width, const float height, const vec3& color) {
glBegin(GL_QUADS);
glColor3fv(&color.x);
glVertex2f(0, 0);
glVertex2f(width, 0);
glVertex2f(width, height);
glVertex2f(0, height);
glEnd();
}
void drawHexagon(const float radius, const vec3& color) {
glBegin(GL_POLYGON);
glColor3fv(&color.x);
for (int i = 0; i < 6; ++i) {
glVertex2f(radius * cos(i * 60 * pi / 180.0),
radius * sin(i * 60 * pi / 180.0));
}
glEnd();
}

SDL jest tutaj do tworzenia okna i zainicjowania OpenGLa, ale dla grafiki tylko 2D to może się on bez niego obejść. Osobiście dla mnie OGL jest wygodniejszy i ma więcej możliwości dlatego wole z niego korzystać nawet do grafiki dwuwymiarowej.
Sprawdź też koniecznie SFML https://www.sfml-dev.org/ . Dość ciekawa biblioteka w funkcjonalności podobna do SDLa. W przeciwieństwie do SDL napisana w stylu obiektowym.