Be The First To Get Support Updates
Want to know about the latest technical content and software updates?
Summary
OpenGL is an industry standard 3D graphics API. OpenGL 4.1 or later is required to run CityEngine 2022.0. For more information, refer to the CityEngine system requirements. OpenGL drivers are usually installed together with the rest of the graphics driver and support software (such as DirectX).
Procedure
Follow the instructions provided to check the type of graphics card installed on the system and the version of OpenGL running.
- Check the graphics card type (Windows):
- Click Start, type dxdiag, and press Enter to access a diagnostic tool listing the graphics card information.
- Click the Display tab.
- Install the OpenGL Extensions Viewer to determine the OpenGL version (Windows, Mac, and Android mobile devices).
Warning: User discretion is advised when installing third-party software. Esri is not liable for the potential risks involved.
- Windows: Go to OpenGL Extensions Viewer (Windows) to download and install the OpenGL Extensions Viewer.
- Mac and Android mobile devices: Go to OpenGL Extensions Viewer (Windows), and click the appropriate link to download the OpenGL Extensions Viewer from the Mac App Store, iTunes Store, or the Android Market, depending on the device and operating system.
The OpenGL Extensions Viewer is a free application designed by Realtech VR. The viewer displays the current version of OpenGL installed, and provides tools to test or update the graphics card driver.
Related Information
- OpenGL Extensions Viewer (Windows)
Last Published: 10/5/2022
Article ID: 000011375
Software: Esri CityEngine 2011.1, 2010.3, 2010.2, 2010.1 ArcGIS CityEngine 2022.0, 2021.1, 2021.0, 2020.1, 2020.0, 2019.1, 2019.0, 2018.1, 2018.0, 2017.1, 2017.0, 2016.1, 2016.0, 2015.2, 2015.1, 2015.0, 2014.1, 2014.0, 2013.1, 2012.1, 2011.2, 2011.1, 2010
I started writing programs, in C (for now) using GLFW and OpenGL. The question I have is that, how do I know which version of OpenGL my program will use? My laptop says that my video card has OpenGL 3.3. Typing «glxinfo | grep -i opengl» returns:
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce 9600M GT/PCI/SSE2
OpenGL version string: 3.3.0 NVIDIA 285.05.09
OpenGL shading language version string: 3.30 NVIDIA via Cg compiler
OpenGL extensions:
So is OpenGL 3.3 automatically being used ?
asked Oct 26, 2011 at 21:49
2
Just call glGetString(GL_VERSION)
(once the context is initialized, of course) and put out the result (which is actually the same that glxinfo does, I suppose):
printf("%sn", glGetString(GL_VERSION));
Your program should automatically use the highest possible version your hardware and driver support, which in your case seems to be 3.3. But for creating a core-profile context for OpenGL 3+ (one where deprecated functionality has been completely removed) you have to take special measures. But since version 2.7 GLFW has means for doing this, using the glfwOpenWindowHint
function. But if you don’t want to explicitly disallow deprecated functionality, you can just use the context given to you by the default context creation functions of GLFW, which will as said support the highest possible version for your hardware and drivers.
But also keep in mind that for using OpenGL functionality higher than version 1.1 you need to retrieve the corresponding function pointers or use a library that handles this for you, like GLEW.
answered Oct 26, 2011 at 22:15
Christian RauChristian Rau
44.9k10 gold badges111 silver badges185 bronze badges
4
I have about 50 PCs on a network I look after and would like to know if the PCs have OpenGL installed. If they have I’d also like to know which version.
Now I don’t mind visiting every machine in-order to do this but I’d prefer not installing any utility.
So is there anyway to find if OpenGL is installed on a PC (I’m thinking of either XP, Vista or 7)? and if installed, which version it is?
If there isn’t, I’m open to utility suggestions as well.
asked Jun 17, 2011 at 9:52
ThomasThomas
2,4104 gold badges20 silver badges30 bronze badges
I believe Windows comes with OpenGL drivers. http://www.opengl.org/wiki/Getting_started seems to confirm this:
If you are running Windows 98/Me/NT/2000/XP/2003/Vista, the OpenGL library has already been installed on your system.
The above page shows the default location for opengl32.dll on the different versions of windows too. E.g. windowssystem32opengl32.dll So you could look there for them on each machine.
If you want to determine the version on each system then I think you’ll need a utility.
answered Jun 17, 2011 at 10:17
Chris KentChris Kent
1,40111 silver badges14 bronze badges
1
Found OpenGL Extensions Viewer. But it’s a utility answer.
answered Jun 17, 2011 at 10:07
ThomasThomas
2,4104 gold badges20 silver badges30 bronze badges
1
There is another utility called GPU Caps Viewer on Geeks3D.
GPU Caps Viewer is a graphics card information utility focused on the OpenGL, Vulkan, OpenCL and CUDA API level support of the main (primary) graphics card. For Vulkan, OpenCL and CUDA, GPU Caps Viewer details the API support of each capable device available in the system.
answered Oct 26, 2016 at 15:00
JanHicksonJanHickson
611 silver badge2 bronze badges
2
В статье глубже описана структура API OpenGL, обработка ошибок, работа с расширениями и получение информации о возможностях драйвера.
Содержание
Структура API OpenGL
API OpenGL описан на языке C без применения C++ ради простоты и платформонезависимости. Он состоит только из функций, констант и примитивных типов, объявленных через typedef
, таких как "typedef int GLenum;"
.
Функции делятся на две группы:
- команды (англ. commands) для изменения состояния драйвера
- запросы (англ. queries) состояния драйвера
Вот несколько примеров:
- функция-команда
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
устанавливает цвет очистки; RGBA компоненты цвета передаются как число с плавающей точкой на отрезке[0..1]
. - функция-команда
void glClear()
очищает буфер кадра путём заливки пикселей цветом очистки. - функция-запрос
const GLubyte *glGetString(GLenum name)
возвращает строковое значение некоторой константы или величины в видеодрайвере, выбор величины зависит от параметраname
; при этомconst GLubyte*
можно преобразовать вconst char*
с помощьюreinterpret_cast
. - тип данных
GLclampf
означает “число с плавающей точкой на отрезке[0..1]
”; при этом никаких проверок принадлежности диапазону компилятор делать не будет, потому что тип объявлен просто какtypedef float GLclampf
.
Функции-команды ничего не возвращают, даже статуса своего выполнения. Это даёт возможность выполнить команду асинхронно, не заставляя приложение ждать, пока видеодрайвер отправит данные на видеокарту и получит от неё ответ.
Обработка ошибок
OpenGL старательно обрабатывает ошибки, такие как “недопустимый аргумент”, “неправильная константа enum”, “несвоевременный вызов команды”. Узнать о наличии общей ошибки в одной из предыдущих функций-команд можно функцией-запросом GLenum glGetError()
.
- Если функция возвращает
GL_NO_ERROR
, ошибок не было - В противном случае код ошибки обозначает категорию ошибки без конкретных указаний
- Функция не только возвращает код ошибки, но и очищает флаг ошибки в драйвере
Условно, код может выглядеть так:
void ValidateGLErrors()
{
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
std::string message;
// с помощью switch превращаем GLenum в строковое описание
// печатаем строку или делаем ещё что-то в целях отладки
}
}
Функцию можно улучшить, если учесть следующее:
- Распечатать строку ошибки можно в поток ошибок
std::cerr
- Любую ошибку можно считать фатальной, вызывая
std::abort
для аварийного завершения программы после вывода текста ошибки - Функцию можно сделать статическим методом класса CUtils
Представим улучшенную версию:
void CUtils::ValidateOpenGLErrors()
{
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
std::string message;
switch (error)
{
case GL_INVALID_ENUM:
message = "invalid enum passed to GL function (GL_INVALID_ENUM)";
break;
case GL_INVALID_VALUE:
message = "invalid parameter passed to GL function (GL_INVALID_VALUE)";
break;
case GL_INVALID_OPERATION:
message = "cannot execute some of GL functions in current state (GL_INVALID_OPERATION)";
break;
case GL_STACK_OVERFLOW:
message = "matrix stack overflow occured inside GL (GL_STACK_OVERFLOW)";
break;
case GL_STACK_UNDERFLOW:
message = "matrix stack underflow occured inside GL (GL_STACK_UNDERFLOW)";
break;
case GL_OUT_OF_MEMORY:
message = "no enough memory to execute GL function (GL_OUT_OF_MEMORY)";
break;
default:
message = "error in some GL extension (framebuffers, shaders, etc)";
break;
}
std::cerr << "OpenGL error: " << message << std::endl;
std::abort();
}
}
После добавления этого метода можно улучшить основной цикл приложения:
// Очистка буфера кадра, обновление и рисование сцены, вывод буфера кадра.
if (running)
{
m_pImpl->Clear();
const float deltaSeconds = chronometer.GrabDeltaTime();
OnUpdateWindow(deltaSeconds);
OnDrawWindow(m_pImpl->GetWindowSize());
CUtils::ValidateOpenGLErrors();
m_pImpl->SwapBuffers();
}
Расширения OpenGL
В целях максимальной гибкости, все изменения в OpenGL вносятся в виде расширений. Расширение OpenGL — это задокументированная спецификация, которая описывает новые функции и их поведение, изменения в поведении старых функций и новые константы. Каждое расширение имеет имя, например, "GL_ARB_multitexture"
. При выпуске новой версии OpenGL часть расширений попадает в новую версию и становится частью ядра OpenGL. Таким образом, в версии OpenGL 3.0 и выше вы автоматически получаете ряд возможностей, которые в OpenGL 1.2 были доступны только как расширения.
- В UNIX-системах и на мобильных устройствах доступны достаточно свежие версии OpenGL (обычно 3.0 и выше), где многие важные расширения уже стали частью ядра стандарта.
- В Windows версии старше OpenGL 1.1 напрямую недоступны, но разработчики драйверов дают доступ к ним через механизм расширений. Если видеодрайвер не установлен, будет доступен только OpenGL 1.1, обладающий весьма ограниченными возможностями.
Функция, описанная в расширении, может не существовать в конкретной реализации OpenGL (если она не поддерживает данное расширение). Поэтому программист должен
- либо запросить адрес функции и использовать её, только если адрес ненулевой
- либо проверить наличие поддержки расширения по его имени и потом смело запрашивать адреса описанных в расширении функций
В стандарте OpenGL не описан способ получения адреса, и каждая операционная система или мультимедийная библиотека предоставляет свой способ. В SDL2 есть функция void *SDL_GL_GetProcAddress(const char *proc)
, которая по имени OpenGL-функции возвращает её адрес или nullptr
, если функция недоступна.
Получение информации о версии OpenGL
Один и тот же видеодрайвер может создать разные констексты с разными версиями OpenGL и разными наборами расширений. Поэтому получать версионную информацию следует уже после создания контекста.
Для получения информации мы применим функцию-запрос glGetString
с тремя различными параметрами. На эту тему есть статья Get Context Info (opengl.org).
- константа с именем GL_VERSION возвращает строку версии OpenGL, причём в начале строки обязательно стоит
"<номер мажорной версии>.<номер минорной версии> "
, а остальная часть строки не определена. Например, строка"3.0 Mesa 10.3.2"
обозрачает “OpenGL версии 3.0, реализуемый подсистемой графики Mesa версии 10.3.2”. - константа с именем GL_VENDOR возвращает имя поставщика реализации OpenGL. Например, строка
"Intel Open Source Technology Center"
обозначает “Видеодрайвер предоставлен OpenSource-подразделением корпорации Intel”. - константа с именем GL_EXTENSIONS содержит полный список расширений, разделённый пробелами. Список обычно насчитывает свыше ста расширений.
Функция печати информации о контексте
void PrintOpenGLInfo()
{
std::string version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
std::string vendorInfo = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
std::string extensionsInfo = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
std::cerr << "OpenGL version: " << version << std::endl;
std::cerr << "OpenGL vendor: " << vendorInfo << std::endl;
std::cerr << "Full OpenGL extensions list: " << extensionsInfo << std::endl;
}
Следуя “правилу трёх ударов”, можно отрефакторить этот код:
void PrintOpenGLInfo()
{
auto printOpenGLString = [](const char *description, GLenum name) {
std::string info = reinterpret_cast<const char *>(glGetString(name));
std::cerr << description << info << std::endl;
};
printOpenGLString("OpenGL version: ", GL_VERSION);
printOpenGLString("OpenGL vendor: ", GL_VENDOR);
printOpenGLString("Full OpenGL extensions list: ", GL_EXTENSIONS);
}
Библиотека GLEW
- Сайт проекта: http://glew.sourceforge.net/
- В Debian/Ubuntu доступна в пакете
libglew-dev
Запрашивать функции и проверять расширения вручную не всегда удобно. Для решения этой типовой задачи создана библиотека GLEW
(сокращение от “openGL Extensions Wrapper”). С помощью макросов и отложенной загрузки адресов функций эта библиотека позволяет использовать расширения так, как будто бы никаких расширений не существует:
- вы просто вызываете функции по имени; если функции нет, произойдёт разыменование нулевого указания
- также вы можете использовать модифицированное имя расширения (с префиксом “GLEW_” вместо “GL_”) как целочисленную переменную со значением 0 или 1; 1 означает, что расширение есть и доступно, 0 означает, что расширения нет или оно недоступно
- если расширение недоступно, вы не должны вызывать функции расширения, чтобы не получить разыменование нулевого указателя
- если при создании контекста OpenGL вы потребовали и получили контекст не ниже определённой версии, то можно даже не проверять расширения, вошедшие в эту версию: они есть.
Подключать заголовок glew.h
следует до первого включения gl.h
, иначе вы получите ошибку при компиляции.
// Правильно
#include <GL/glew.h>
#include <GL/gl.h>
// Неправильно!
#include <GL/gl.h>
#include <GL/glew.h>
Библиотека GLEW требует явного вызова функции glewInit для своей инициализации. Сделать вызов следует только один раз. Чтобы не накладывать на класс CAbstractWindow
лишних ограничений, нужно гарантировать, что при первом конструировании объекта CAbstractWindow
функция будет вызвана, а при последующих — уже нет. Также надо установить глобальную переменную-флаг glewExperimental
, чтобы GLEW оборачивала функции из версий OpenGL 3.x и 4.x.
Для этой цели можно использовать два подхода
- взять из стандартного заголовка
<mutex>
функцию std::call_once - завести в функции статическую переменную типа bool, которая будет устанавливаться в false в инициализаторе (который для статических переменных внутри функции вызывается ровно один раз)
В многопоточной среде было бы правильным использовать call_once, чтобы исключить возможность повторного вызова инициализации во время выполнения “glewInit” в другом потоке. Однако, ни контекст OpenGL, ни GLEW не могут использоваться из нескольких потоков одновременно. Поэтому call_once нам не потребуется, и достаточно статической переменной типа bool:
void CUtils::InitOnceGLEW()
{
static bool didInit = false;
if (!didInit)
{
glewExperimental = GL_TRUE;
GLenum status = glewInit();
if (status != GLEW_OK)
{
std::cerr << "GLEW initialization failed: " << glewGetErrorString(status) << std::endl;
std::abort();
}
}
}
Узнаём о расширениях через GLEW
Читать полный список расширений, полученный через glGetString(GL_EXTENSIONS)
, не очень удобно. Сканировать его программно слишком трудоёмко в плане вычислений.
Для удобного получения расширений у GLEW есть переменные-флаги, которые устанавливаются при вызове glewInit()
. Для проверки наличия расширения надо:
- найти идентификатор расширения в реестре расширений (opengl.org), например,
GL_ARB_vertex_shader
- заменить префикс
GL_
наGLEW_
- написать проверку переменной-флага с таким именем
Теперь можно улучшить функцию PrintOpenGLInfo
:
void PrintOpenGLInfo()
{
auto printOpenGLString = [](const char *description, GLenum name) {
std::string info = reinterpret_cast<const char *>(glGetString(name));
std::cerr << description << info << std::endl;
};
printOpenGLString("OpenGL version: ", GL_VERSION);
printOpenGLString("OpenGL vendor: ", GL_VENDOR);
if (GLEW_ARB_vertex_shader)
{
std::cerr << "Has vertex shaders" << std::endl;
}
else
{
std::cerr << "Has no vertex shaders" << std::endl;
}
if (GLEW_ARB_fragment_shader)
{
std::cerr << "Has fragment shaders" << std::endl;
}
else
{
std::cerr << "Has no fragment shaders" << std::endl;
}
if (GLEW_ARB_vertex_buffer_object)
{
std::cerr << "Has vertex buffers" << std::endl;
}
else
{
std::cerr << "Has vertex busffers" << std::endl;
}
if (GLEW_ARB_framebuffer_object)
{
std::cerr << "Has framebuffers" << std::endl;
}
else
{
std::cerr << "Has framebuffers" << std::endl;
}
}
Рефакторим код:
void PrintOpenGLInfo()
{
auto printOpenGLString = [](const char *description, GLenum name) {
std::string info = reinterpret_cast<const char *>(glGetString(name));
std::cerr << description << info << std::endl;
};
printOpenGLString("OpenGL version: ", GL_VERSION);
printOpenGLString("OpenGL vendor: ", GL_VENDOR);
auto testExtension = [](const char *description, GLboolean supportFlag) {
const char *prefix = supportFlag ? "Has " : "Has no ";
std::cerr << prefix << description << std::endl;
};
testExtension("vertex shaders", GLEW_ARB_vertex_shader);
testExtension("fragment shaders", GLEW_ARB_fragment_shader);
testExtension("vertex buffers", GLEW_ARB_vertex_buffer_object);
testExtension("framebuffers", GLEW_ARB_framebuffer_object);
}
На машине с Ubuntu 14.04 и встроенной видеокартой Intel программа выводит следующее:
OpenGL version: 3.0 Mesa 10.3.2
OpenGL vendor: Intel Open Source Technology Center
Has vertex shaders
Has fragment shaders
Has vertex buffers
Has framebuffers
На машине с Windows 8 и видеокартой Intel вывод отличается:
OpenGL version: 4.4.0 - Build 20.19.15.4377
OpenGL vendor: Intel
Has vertex shaders
Has fragment shaders
Has vertex buffers
Has framebuffers
Создаём работоспособное приложение
Код запроса версии OpenGL разместим в классе CWindow
, потому что в дальнейших примерах нам уже не нужно будет печатать что-либо в консоль.
Файл Window.h
#pragma once
#include "AbstractWindow.h"
class CWindow : public CAbstractWindow
{
// CAbstractWindow interface
protected:
void OnWindowEvent(const SDL_Event &event) override;
void OnUpdateWindow(float deltaSeconds) override;
void OnDrawWindow(const glm::ivec2 &size) override;
private:
void PrintOpenGLInfo();
};
листинг Window.cpp
#include "stdafx.h"
#include "Window.h"
#include <mutex>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cctype>
namespace
{
std::once_flag g_didPrintOpenGLInfo;
}
void CWindow::OnWindowEvent(const SDL_Event &event)
{
(void)event;
}
void CWindow::OnUpdateWindow(float deltaSeconds)
{
(void)deltaSeconds;
}
void CWindow::OnDrawWindow(const glm::ivec2 &size)
{
(void)size;
std::call_once(g_didPrintOpenGLInfo, &CWindow::PrintOpenGLInfo, this);
}
void CWindow::PrintOpenGLInfo()
{
auto printOpenGLString = [](const char *description, GLenum name) {
std::string info = reinterpret_cast<const char *>(glGetString(name));
std::cerr << description << info << std::endl;
};
printOpenGLString("OpenGL version: ", GL_VERSION);
printOpenGLString("OpenGL vendor: ", GL_VENDOR);
auto testExtension = [](const char *description, GLboolean supportFlag) {
const char *prefix = supportFlag ? "Has " : "Has no ";
std::cerr << prefix << description << std::endl;
};
testExtension("vertex shaders", GLEW_ARB_vertex_shader);
testExtension("fragment shaders", GLEW_ARB_fragment_shader);
testExtension("vertex buffers", GLEW_ARB_vertex_buffer_object);
testExtension("framebuffers", GLEW_ARB_framebuffer_object);
}
First thing to deal with OpenGL is to know which version you have on your operating system.
For this tutorial we will test it on Windows.
And because we are testing the OpenGL version, we will also check what is the FreeGLUT and GLEW version.
Explanation
To create code for OpenGL 3.3, you have to have a graphic card that handles OpenGL 3.3.
If you don’t know which version you have, the code below will show you this.
For example, in the video, you could see that I have a 3.3 OpenGL version.
So I can create graphics with OpenGL 3.3 but I can’t do this with OpenGL 4+.
We assume that for this tutorial you have already set up your environment, with for example Visual Studio.
The code below has been split into several functions in order to focus only on the libraries version.
Notice that you can close the application by pressing the ESC key.
The code
#include <GLglew.h> // the opengl library wrapped by extended features #include <GLfreeglut.h> // library cross-platform toolkit windows and managing input operations #include <iostream> #include <string> #include <sstream> using namespace std; /** * analyse the version */ string makeMeString(GLint versionRaw) { stringstream ss; string str = ""; ss << versionRaw; // transfers versionRaw value into "ss" str = ss.str(); // sets the "str" string as the "ss" value return str; } /** * Format the string as expected */ void formatMe(string *text) { string dot = "."; text->insert(1, dot); // transforms 30000 into 3.0000 text->insert(4, dot); // transforms 3.0000 into 3.00.00 } /** * Message */ void consoleMessage() { const char *versionGL = ""; GLint versionFreeGlutInt = 0; versionGL = (char *)(glGetString(GL_VERSION)); versionFreeGlutInt = (glutGet(GLUT_VERSION)); string versionFreeGlutString = makeMeString(versionFreeGlutInt); formatMe(&versionFreeGlutString); cout << endl; cout << "OpenGL version: " << versionGL << endl << endl; cout << "FreeGLUT version: " << versionFreeGlutString << endl << endl; cout << "GLEW version: " << GLEW_VERSION << "." << GLEW_VERSION_MAJOR << "." << GLEW_VERSION_MINOR << "." << GLEW_VERSION_MICRO << endl; } /** * Manager error */ void managerError() { if (glewInit()) { // checks if glewInit() is activated cerr << "Unable to initialize GLEW." << endl; while (1); // let's use this infinite loop to check the error message before closing the window exit(EXIT_FAILURE); } // FreeConsole(); } /** * Manage display (to be implemented) */ void managerDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // clear the screen glutSwapBuffers(); } /** * Initialize FREEGLUT */ void initFreeGlut(int ac, char *av[]) { // A. init glutInit(&ac, av); // 1. inits glut with arguments from the shell glutInitDisplayString(""); // 2a. sets display parameters with a string (obsolete) glutInitDisplayMode(GLUT_SINGLE); // 2b. sets display parameters with defines glutInitWindowSize(600, 600); // 3. window size glutInitContextVersion(3, 3); // 4. sets the version 3.3 as current version (so some functions of 1.x and 2.x could not work properly) glutInitContextProfile(GLUT_CORE_PROFILE); // 5. sets the version 3.3 for the profile core glutInitWindowPosition(500, 500); // 6. distance from the top-left screen // B. create window glutCreateWindow("BadproG - Hello world :D"); // 7. message displayed on top bar window } /** * Manage keyboard */ void managerKeyboard(unsigned char key, int x, int y) { if (key == 27) { // 27 = ESC key exit(0); } } /** * Main, what else? */ int main(int argc, char** argv) { initFreeGlut(argc, argv); // inits freeglut managerError(); // manages errors consoleMessage(); // displays message on the console // C. register the display callback function glutDisplayFunc(managerDisplay); // 8. callback function glutKeyboardFunc(managerKeyboard); // D. main loop glutMainLoop(); // 9. infinite loop return 0; }
Conclusion
A good way to avoid searching everywhere on your operating system, which OpenGL version you have.
Great job, once again you’ve made it.