OpenGL (Open Graphics Library) — это открытая кроссплатформенная спецификация программного интерфейса (API), через который программа просит видеокарту нарисовать 2D- и 3D-графику. Сам по себе OpenGL — не библиотека, которую скачивают, а документ-стандарт: его ведет консорциум Khronos Group, а реализуют производители GPU в своих драйверах. Последняя версия — OpenGL 4.6 (2017).
Содержание
- Мини-словарь: что именно называют «OpenGL»
- Графический конвейер: от вершин к пикселям
- Старый и современный OpenGL
- Минимальная программа: треугольник на шейдерах
- Версии OpenGL
- OpenGL на macOS
- OpenGL vs Vulkan, DirectX 12 и Metal
- Где OpenGL используют в 2026 году
- Выводы
- Где применяется / связь с практикой
- FAQ
Ниже — конвейер и шейдеры, программа с треугольником, версии и сравнение с Vulkan, DirectX 12 и Metal.
Мини-словарь: что именно называют «OpenGL»
Словом «OpenGL» называют четыре разные вещи:
| Термин | Что это | Пример |
|---|---|---|
| Спецификация | Документ: какие функции есть и как работают | OpenGL 4.6 Core Profile |
| Реализация | Код в драйвере видеокарты, который исполняет вызовы | драйвер NVIDIA, AMD, Intel, Mesa в Linux |
| Контекст | Объект со всем состоянием OpenGL, привязанный к окну или буферу | создается через SDL, GLFW или системные WGL/GLX/EGL |
| GLSL | Отдельный язык шейдеров — программ, которые исполняет GPU | #version 330 core |
Поэтому «установить OpenGL» обычно значит обновить драйвер, а версия зависит от драйвера и GPU. Лицензии GNU у OpenGL нет: это открытый стандарт, реализации лицензируются по-разному (драйверы вендоров закрытые, Mesa — MIT-подобная).
Графический конвейер: от вершин к пикселям
Видеокарта рисует треугольники (плюс точки и линии). Путь данных через GPU называют графическим конвейером (pipeline). Упрощенная схема:
- Данные вершин. Координаты, цвета, нормали лежат в буфере на GPU (VBO), их формат описывает VAO.
- Вершинный шейдер для каждой вершины применяет матрицы модели, камеры и проекции и выдает координаты в пространстве отсечения (clip space). В пиксели их переводит фиксированная стадия после отсечения (деление на
w, viewport). - Тесселяция и геометрический шейдер (необязательно) — дробят или порождают примитивы.
- Сборка примитивов и отсечение всего, что вне поля зрения.
- Растеризация. Треугольник превращается в набор фрагментов — кандидатов в пиксели.
- Фрагментный шейдер вычисляет цвет каждого фрагмента: текстуры, освещение.
- Тесты и смешивание. Тест глубины отбрасывает скрытые фрагменты, blending дает прозрачность, результат идет в буфер кадра.
Схема упрощена (ранний тест глубины может идти до фрагментного шейдера), но контракт для программиста такой. Стадии 2, 3, 6 программируются шейдерами, остальные настраиваются вызовами вроде glEnable(GL_DEPTH_TEST). Вне конвейера с версии 4.3 есть вычислительные (compute) шейдеры.
Старый и современный OpenGL
Многие уроки до сих пор показывают glBegin/glEnd, glVertex3f и glLight. Это фиксированный конвейер (fixed function) OpenGL 1.x-2.x: программа лишь включала режимы, GPU делал остальное по жестким правилам.
В OpenGL 3.0 (2008) эти функции объявили устаревшими, а с 3.2 (2009) появились два профиля:
- Core profile — только современный API: буферы, VAO, шейдеры.
- Compatibility profile — старое и новое вместе; на macOS его нет выше версии 2.1.
Для учебы берите core profile. GLU, GLUT и GLAUX — тоже наследие: сегодня окно создают через GLFW или SDL, функции загружают glad или GLEW, матрицы берут из GLM.
Минимальная программа: треугольник на шейдерах
Полный пример на C++ с SDL2: контекст OpenGL 3.3 core, два шейдера, оранжевый треугольник. Чтобы проверить результат без глаз, программа читает цвет пикселей из буфера кадра.
// triangle.cpp - минимальная программа OpenGL 3.3 core: окно, шейдеры, треугольник
#include <SDL.h>
#ifdef __APPLE__
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl3.h>
#else
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#include <cstdio>
// Вершинный шейдер: для каждой вершины
static const char* kVertexSrc = R"(#version 330 core
layout(location = 0) in vec2 aPos;
void main() { gl_Position = vec4(aPos, 0.0, 1.0); }
)";
// Фрагментный шейдер: для каждого фрагмента
static const char* kFragmentSrc = R"(#version 330 core
out vec4 FragColor;
void main() { FragColor = vec4(1.0, 0.5, 0.0, 1.0); }
)";
static GLuint compile(GLenum type, const char* src) {
GLuint s = glCreateShader(type);
glShaderSource(s, 1, &src, nullptr);
glCompileShader(s);
GLint ok = 0;
glGetShaderiv(s, GL_COMPILE_STATUS, &ok);
if (!ok) {
char log[1024];
glGetShaderInfoLog(s, sizeof log, nullptr, log);
std::fprintf(stderr, "shader error:\n%s\n", log);
}
return s;
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_Window* win = SDL_CreateWindow("OpenGL", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 400, 400, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
SDL_GLContext ctx = win ? SDL_GL_CreateContext(win) : nullptr;
if (!ctx) { std::fprintf(stderr, "no GL context: %s\n", SDL_GetError()); return 1; }
std::printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
std::printf("GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
// 1. Данные: три вершины треугольника в координатах [-1; 1]
float verts[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.0f, 0.5f };
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof verts, verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
// 2. Программа из двух шейдеров
GLuint prog = glCreateProgram();
glAttachShader(prog, compile(GL_VERTEX_SHADER, kVertexSrc));
glAttachShader(prog, compile(GL_FRAGMENT_SHADER, kFragmentSrc));
glLinkProgram(prog);
GLint linked = 0;
glGetProgramiv(prog, GL_LINK_STATUS, &linked);
if (!linked) { std::fprintf(stderr, "link failed\n"); return 1; }
// 3. Кадр: очистить экран и нарисовать
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(prog);
glDrawArrays(GL_TRIANGLES, 0, 3);
glFinish();
// Проверка: читаем пиксели из буфера кадра
int w, h;
SDL_GL_GetDrawableSize(win, &w, &h);
unsigned char center[4], corner[4];
glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, center);
glReadPixels(1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, corner);
std::printf("center: %d %d %d\n", center[0], center[1], center[2]);
std::printf("corner: %d %d %d\n", corner[0], corner[1], corner[2]);
std::printf("glGetError: %u\n", glGetError());
SDL_GL_SwapWindow(win);
SDL_GL_DeleteContext(ctx);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
Сборка на macOS (проверено: macOS 26.4, Apple clang 21, SDL 2.32.10, Apple Silicon):
clang++ -std=c++17 -Wall -Wextra triangle.cpp $(sdl2-config --cflags --libs) -framework OpenGL -o triangle
./triangle
Вывод:
GL_VERSION: 4.1 Metal - 90.5
GLSL: 4.10
center: 255 128 0
corner: 26 26 26
glGetError: 0
Центр — оранжевый треугольник (0.5 от 255 = 128), угол — фон 0.1. Попросили 3.3, драйвер выдал совместимую 4.1, и на Apple Silicon OpenGL работает поверх Metal. Чтение пикселей скрытого окна — наблюдение прогона, не гарантия: по спецификации содержимое невидимого окна не определено, надежнее рисовать в свой framebuffer object. В Linux программа собирается с -lGL вместо -framework OpenGL; в Windows функции новее 1.1 загружают через glad или GLEW, системная opengl32.dll их не экспортирует.
SDL2 — ветка на поддержке, актуальна SDL3 (3.4.x). В ней другой заголовок <SDL3/SDL.h>, SDL_CreateWindow(title, w, h, flags) без позиции, SDL_GL_DestroyContext и SDL_GetWindowSizeInPixels вместо SDL_GL_DeleteContext и SDL_GL_GetDrawableSize; вызовы OpenGL те же.
OpenGL — машина состояний: glBind... и glUse... выбирают «текущий» объект, и следующие вызовы работают с ним.
Типовая ошибка: шейдер из старого урока
Фрагментный шейдер из урока под OpenGL 2.x в core-контексте:
static const char* kFragmentSrc = R"(#version 330 core
void main() { gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); }
)";
Результат на том же macOS (stderr; строки GL_VERSION и GLSL как раньше):
shader error:
ERROR: 0:2: Use of undeclared identifier 'gl_FragColor'
link failed
Встроенной gl_FragColor в core-профиле нет. Исправление — свой выход out vec4 FragColor;, как в основном примере. Текст ошибки зависит от драйвера (у NVIDIA, AMD и Mesa другой). Всегда проверяйте GL_COMPILE_STATUS и GL_LINK_STATUS: без них программа молча нарисует пустой экран, а glGetError вернет лишь 1282 (GL_INVALID_OPERATION).
Версии OpenGL
| Версия | Год | Что появилось |
|---|---|---|
| 1.0 | 1992 | Первая спецификация (Silicon Graphics) |
| 1.5 | 2003 | Буферы вершин (VBO) |
| 2.0 | 2004 | Язык шейдеров GLSL |
| 3.0 / 3.2 | 2008 / 2009 | Устаревание, профили core/compatibility, геометрические шейдеры |
| 3.3 | 2010 | База большинства учебников |
| 4.0 | 2010 | Тесселяция |
| 4.3 | 2012 | Compute-шейдеры, отладочный вывод |
| 4.5 | 2014 | Direct State Access — работа с объектами без привязки |
| 4.6 | 2017 | Прием шейдеров в формате SPIR-V (как в Vulkan) |
С 2017 года новых версий OpenGL нет (на сентябрь 2026): Khronos развивает Vulkan, OpenGL живет расширениями. Для мобильных есть ветка OpenGL ES (последняя 3.2), на ES 3.0 основан WebGL 2. Свою версию покажет строка GL_VERSION из примера, в Linux — glxinfo -B (mesa-utils), в Windows — GPU-Z.
OpenGL на macOS
Apple объявила OpenGL устаревшим в macOS 10.14 Mojave (2018) и перешла на Metal. OpenGL в системе остался (проверено на macOS 26.4), но замер на 4.1: compute-шейдеров, DSA и других возможностей 4.2-4.6 нет. Без GL_SILENCE_DEPRECATION компилятор засыпает предупреждениями, а программу под OpenGL 4.3+ на Mac придется переписывать.
OpenGL vs Vulkan, DirectX 12 и Metal
| OpenGL | Vulkan | Direct3D 12 | Metal | |
|---|---|---|---|---|
| Кто ведет | Khronos Group | Khronos Group | Microsoft | Apple |
| Платформы | Windows, Linux, macOS (до 4.1), ES — мобильные | Windows, Linux, Android; на Apple — через MoltenVK | Windows, Xbox | macOS, iOS, iPadOS |
| Уровень | Высокий: память и синхронизация на драйвере | Явный: память, синхронизация, буферы команд на программисте | Явный | Явный, компактнее Vulkan |
| Шейдеры | GLSL (SPIR-V с 4.6) | SPIR-V (пишут на GLSL, HLSL и др.) | HLSL | Metal Shading Language |
| Многопоточность | Контекст активен в одном потоке | Запись команд из многих потоков | Да | Да |
| Порог входа | Треугольник — около 100 строк | Треугольник — порядка 1000 строк | Высокий | Средний |
Как выбирать: учиться графике — OpenGL 3.3 core (понятия переносятся в любой API); производительность на Linux и Android — Vulkan; только Windows и Xbox — Direct3D 12; только Apple — Metal; игра, а не движок — Unity, Unreal Engine или Godot, они выбирают API сами. Цена высокого уровня OpenGL: драйвер скрыто проверяет состояние, и при тысячах вызовов отрисовки на кадр он обычно раньше Vulkan упирается в процессор (насколько — зависит от сцены и драйвера).
Где OpenGL используют в 2026 году
В CAD, научной визуализации и учебных курсах. Жизнь ему продлевают трансляторы: Zink в Mesa исполняет OpenGL поверх Vulkan, ANGLE — OpenGL ES поверх Direct3D, Vulkan или Metal (так WebGL работает в Chrome на Windows). Новые нагруженные проекты чаще берут явные API, в вебе — WebGPU.
Выводы
- OpenGL — открытая спецификация Khronos Group; реализует ее драйвер, версия зависит от GPU и драйвера.
- Современный OpenGL — core profile, буферы и шейдеры GLSL;
glBegin/glEnd, GLU и GLUT — наследие фиксированного конвейера. - Последняя версия — 4.6 (2017); на macOS OpenGL устарел и ограничен 4.1.
- Vulkan, Direct3D 12 и Metal — явные API с меньшими накладными расходами и большим объемом кода; OpenGL — самый короткий путь к пониманию конвейера.
- Проверяйте компиляцию и линковку шейдеров, иначе ошибка выглядит как пустой экран.
Где применяется / связь с практикой
Освойте тему на практике
Графику на OpenGL и Vulkan чаще всего пишут на C++: движки, CAD, симуляторы. Помимо API нужен уверенный современный C++: RAII-обертки над объектами OpenGL, время жизни ресурсов, многопоточность, CMake. Их системно разбирают на курсе «C++-разработчик. Продвинутый уровень». Послушать преподавателей и попробовать формат можно на бесплатных открытых уроках Otus.
FAQ
Нужно ли скачивать OpenGL отдельно?
Нет, он входит в драйвер видеокарты; для новой версии обычно достаточно обновить драйвер. Для разработки ставят библиотеку окна (GLFW или SDL) и загрузчик функций (glad или GLEW).
Можно ли писать под OpenGL не на C++?
Да: есть привязки для C, Python (PyOpenGL, moderngl), Java (LWJGL), C# (OpenTK), Rust; вызовы и шейдеры те же.



