我想使用ARB扩展来创建OpenGL上下文,但是它不起作用。运行时在控制台上打印的错误消息(我的puts()调用)是:“选择最终的窗口像素格式失败。”和“创建最终渲染上下文失败。”。而且窗口不会显示。
当我删除数组的最后3个属性时,该程序在控制台中不输出任何内容,但在屏幕上不显示任何内容,然后停止(有一个while循环)。这很奇怪。
使用wglGetProcAddress()强制转换的第二个函数指针在用gcc和-Wextra标志编译时会生成警告(对于所有警告)。我不知道为什么,如果有人可以解决这个问题,请告诉我。
代码:
#include <stdio.h>
#define UNICODE
#include <windows.h>
#include <dwmapi.h>
#define GLEW_STATIC
#include <glew.h>
#include <GL\wglext.h>
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp,
LPARAM lp);
unsigned int CreateShaderProgram(char* VertexSource, char* FragmentSource);
int main(void){
WNDCLASSEX FirstWindowClass = {};
FirstWindowClass.cbSize = sizeof(WNDCLASSEX);
FirstWindowClass.style = CS_OWNDC;
FirstWindowClass.lpfnWndProc = FirstWindowProcedure;
FirstWindowClass.lpszClassName = L"FirstWindowClass";
if(!RegisterClassEx(&FirstWindowClass))
puts("Registration of the first window class failed.\n");
HWND FirstWindow = CreateWindowEx(WS_EX_APPWINDOW,
FirstWindowClass.lpszClassName, L"FirstWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FirstWindow == NULL)
puts("Creation of the first window failed.\n");
PIXELFORMATDESCRIPTOR FirstWindowPixelFormatDescriptor = {};
FirstWindowPixelFormatDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
FirstWindowPixelFormatDescriptor.nVersion = 1;
FirstWindowPixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
FirstWindowPixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
FirstWindowPixelFormatDescriptor.cColorBits = 32;
FirstWindowPixelFormatDescriptor.cDepthBits = 24;
FirstWindowPixelFormatDescriptor.cStencilBits = 8;
FirstWindowPixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
HDC FirstWindowDeviceContext = GetDC(FirstWindow);
if(FirstWindowDeviceContext == NULL)
puts("First window device context retrieving failed.\n");
int FirstWindowPixelFormat = ChoosePixelFormat(FirstWindowDeviceContext,
&FirstWindowPixelFormatDescriptor);
if(FirstWindowPixelFormat == 0)
puts("Choosing the first pixel format failed.\n");
if(SetPixelFormat(FirstWindowDeviceContext, FirstWindowPixelFormat,
&FirstWindowPixelFormatDescriptor) == FALSE)
puts("Setting the first pixel format failed.\n");
HGLRC FirstWindowRenderingContext =
wglCreateContext(FirstWindowDeviceContext);
if(FirstWindowRenderingContext == NULL)
puts("Creating the first rendering context failed.\n");
if(wglMakeCurrent(FirstWindowDeviceContext, FirstWindowRenderingContext) ==
FALSE)
puts("Making the first context current failed.\n");
if(glewInit() != GLEW_OK)
puts("Initialisation of GLEW failed.\n");
WNDCLASSEX FinalWindowClass = {};
FinalWindowClass.cbSize = sizeof(WNDCLASSEX);
FinalWindowClass.style = CS_OWNDC;
FinalWindowClass.lpfnWndProc = FinalWindowProcedure;
FinalWindowClass.lpszClassName = L"FinalWindowClass";
if(!RegisterClassEx(&FinalWindowClass))
puts("Registration of the final window class failed\n");
HWND FinalWindow = CreateWindowEx(WS_EX_APPWINDOW,
FinalWindowClass.lpszClassName, L"FinalWindow", WS_POPUP, 0, 0, 10, 10,
NULL, NULL, NULL, NULL);
if(FinalWindow == NULL)
puts("Creation of the final window failed.\n");
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
wglGetProcAddress("wglChoosePixelFormatARB");
if(wglChoosePixelFormatARB == NULL)
puts("Getting the wglChoosePixelFormatARB function pointer failed.\n");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB == NULL)
puts("Getting the wglCreateContextAttribsARB function pointer"
"failed.\n");
int FinalWindowContextAttributes[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 4,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
HDC FinalWindowDeviceContext = GetDC(FinalWindow);
if(FinalWindowDeviceContext == NULL)
puts("Retrieving the final window device cotext failed.\n");
int FinalWindowPixelFormat;
if(FALSE == wglChoosePixelFormatARB(FinalWindowDeviceContext,
FinalWindowContextAttributes, NULL, 1, &FinalWindowPixelFormat, NULL))
puts("Choosing the final window pixel format failed.\n");
HGLRC FinalWindowRenderingContext =
wglCreateContextAttribsARB(FinalWindowDeviceContext, NULL,
FinalWindowContextAttributes);
if(FinalWindowRenderingContext == NULL)
puts("Creating the final rendering context failed.\n");
if(FALSE == wglMakeCurrent(FinalWindowDeviceContext,
FinalWindowRenderingContext))
puts("Making the final context current failed.\n");
DWM_BLURBEHIND blur = {};
blur.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
blur.fEnable = 1;
blur.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
DwmEnableBlurBehindWindow(FinalWindow, &blur);
SetLayeredWindowAttributes(FinalWindow, RGB(0, 0, 0), 255, LWA_COLORKEY);
char VertexShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main(){\n"
" gl_Position = position;\n"
"}";
char FragmentShaderSource[] =
"#version 440 core\n"
"\n"
"layout(location = 0) out vec4 colour;\n"
"\n"
"void main(){\n"
" colour = vec4(0.5, 0.5, 0.5, 1.0);\n"
"}";
float Verticies[] = {
0.0f, 0.5f, // top : 0
0.5f, 0.0f, // right : 1
0.0f, -0.5f, // bottom : 2
-0.5f, 0.0f // left : 3
};
unsigned int Indices[] = {
3, 0, 1, // top
3, 2, 1 // bottom
};
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
unsigned int VertexArray;
glGenVertexArrays(1, &VertexArray);
glBindVertexArray(VertexArray);
unsigned int VertexBuffer;
glGenBuffers(1, &VertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), Verticies, GL_STATIC_DRAW);
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), Indices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned int ShaderProgram = CreateShaderProgram(VertexShaderSource,
FragmentShaderSource);
glUseProgram(ShaderProgram);
glViewport(0, 0, 800, 400);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
ShowWindow(FinalWindow, 1);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0)){
DispatchMessage(&msg);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
wglSwapLayerBuffers(FinalWindowDeviceContext, WGL_SWAP_MAIN_PLANE);
}
}
LRESULT CALLBACK FirstWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
return DefWindowProc(hWnd, uMsg, wp, lp);
}
LRESULT CALLBACK FinalWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wp, LPARAM lp){
switch(uMsg){
case WM_NCHITTEST: return HTCAPTION;
case WM_DESTROY: PostQuitMessage(0); return 0;
default: return DefWindowProc(hWnd, uMsg, wp, lp);
}
}
unsigned int CreateShader(char* Source, unsigned int Type);
unsigned int CreateShaderProgram(char* VertexSource,
char* FragmentSource){
unsigned int ShaderProgram = glCreateProgram(),
VertexShader = CreateShader(VertexSource, GL_VERTEX_SHADER),
FragmentShader = CreateShader(FragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);
glLinkProgram(ShaderProgram);
glValidateProgram(ShaderProgram);
return ShaderProgram;
}
unsigned int CreateShader(char* Source, unsigned int Type){
unsigned int Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char* const*)&Source, NULL);
glCompileShader(Shader);
return Shader;
}
因为您使用glew.h,所以我建议也使用“ wglew.h”。参见The OpenGL Extension Wrangler Library
#include <wglext.h>
#include <GL/wglew.h>
wglew.h处理wgl
* api的动态链接。因此,您可以跳过调用wglGetProcAddress
:
/* DELETE
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
(PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
if(wglChoosePixelFormatARB == NULL)
puts("Getting the wglChoosePixelFormatARB function pointer failed.\n");
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
if(wglCreateContextAttribsARB == NULL)
puts("Getting the wglCreateContextAttribsARB function pointer"
"failed.\n");
*/
if(glewInit() != GLEW_OK)
您需要在glewInit()
之后再次调用wglMakeCurrent()
以获得最终窗口,并且希望立即销毁临时窗口。否则,GLEW将保留之前没有Core Profile的初始化状态。
int FinalWindowContextAttributes [] = {
如上一个问题中所指定,wglChoosePixelFormatARB()
和wglCreateContextAttribsARB()
接受不同的属性列表,因此您需要创建单独的列表。
您可以尝试以下CreateCoreProfile()
方法来创建OpenGL核心配置文件(我想这就是您要寻找的)。该代码段包含wglext.h
中的定义,因此您可以删除它们以使用wglext.h
。它不依赖GLEW,仅依赖WinAPI。
wglSwapLayerBuffers(FinalWindowDeviceContext, WGL_SWAP_MAIN_PLANE);
您应该非常小心,并考虑使用SwapBuffers()
(不带wgl
前缀),因为wglSwapLayerBuffers()
可能会导致非常奇怪的行为,并且我所见过的大多数参考资料都不推荐这样做。但是我想这是您正在考虑考虑SetLayeredWindowAttributes()
电话的问题。
使用wglGetProcAddress()强制转换的函数指针在使用gcc编译时会生成警告
这是一个已知的GCC问题-WGL(wglGetProcAddress()
),GLX和EGL API以及其他许多API都没有其他方法来验证返回的函数指针的签名。这是不安全的(应用程序将在调用具有不同签名的函数时崩溃),但是您无法采取任何措施来修复警告-暂时只能将其删除。
#include <windows.h>
#include <iostream>
#include <GL/gl.h>
//! Auxiliary tool creating WGL rendering context.
class WglWindow
{
private:
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
// WGL_ARB_pixel_format
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_SUPPORT_GDI_ARB 0x200F
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_STEREO_ARB 0x2012
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_NO_ACCELERATION_ARB 0x2025
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_TYPE_COLORINDEX_ARB 0x202C
// WGL_ARB_create_context_profile
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
// WGL_CONTEXT_FLAGS bits
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
// WGL_CONTEXT_PROFILE_MASK_ARB bits
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define GL_NUM_EXTENSIONS 0x821D
typedef const char* (WINAPI *wglGetExtensionsStringARB_t)(HDC theDeviceContext);
typedef BOOL (WINAPI *wglChoosePixelFormatARB_t)(HDC theDevCtx, const int* theIntAttribs,
const float* theFloatAttribs, unsigned int theMaxFormats,
int* theFormatsOut, unsigned int* theNumFormatsOut);
typedef HGLRC (WINAPI *wglCreateContextAttribsARB_t)(HDC theDevCtx, HGLRC theShareContext, const int* theAttribs);
typedef const GLubyte* (WINAPI *glGetStringi_t) (GLenum name, GLuint index);
public:
//! Create OpenGL Core Profile rendering context for specified window.
static HGLRC CreateCoreProfile (HDC theDevCtx,
bool theIsDebugCtx)
{
HGLRC aGlCtx = NULL;
{
WglWindow aCtxTmp (L"wgltemp");
if (!aCtxTmp.CreateDefaultWindow()) { return NULL; }
const char* aWglExts = NULL;
{
wglGetExtensionsStringARB_t wglGetExtensionsStringARB = (wglGetExtensionsStringARB_t )wglGetProcAddress ("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB != NULL) { aWglExts = wglGetExtensionsStringARB (aCtxTmp.myDevCtx); }
}
if (aWglExts == NULL) { return NULL; } // should never happen
// in WGL world wglGetProcAddress() returns NULL if extensions is unavailable, so that checking for extension string can be skipped
//if (checkGlExtension (aWglExts, "WGL_ARB_pixel_format"))
//if (checkGlExtension (aWglExts, "WGL_ARB_create_context_profile"))
wglChoosePixelFormatARB_t aChoosePixProc = (wglChoosePixelFormatARB_t )wglGetProcAddress ("wglChoosePixelFormatARB");
wglCreateContextAttribsARB_t aCreateCtxProc = (wglCreateContextAttribsARB_t )wglGetProcAddress ("wglCreateContextAttribsARB");
if (aCreateCtxProc == NULL) { return NULL; } // core profile cannot be created
const int aPixAttribs[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_STEREO_ARB, GL_FALSE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 24,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
0, 0,
};
unsigned int aFrmtsNb = 0;
int aPixelFrmtId = 0;
if (!aChoosePixProc (theDevCtx, aPixAttribs, NULL, 1, &aPixelFrmtId, &aFrmtsNb)
|| aPixelFrmtId == 0
|| !WglWindow::SetWindowPixelFormat (theDevCtx, aPixelFrmtId))
{
return NULL;
}
int aCoreCtxAttribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, theIsDebugCtx ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
0, 0
};
// Try to create the core profile of highest OpenGL version.
// This will be done automatically by some drivers when requesting 3.2,
// but some will not (e.g. AMD Catalyst) since WGL_ARB_create_context_profile specification allows both implementations.
for (int aLowVer4 = 7; aLowVer4 >= 0 && aGlCtx == NULL; --aLowVer4)
{
aCoreCtxAttribs[1] = 4; aCoreCtxAttribs[3] = aLowVer4;
aGlCtx = aCreateCtxProc (theDevCtx, NULL, aCoreCtxAttribs);
}
for (int aLowVer3 = 3; aLowVer3 >= 2 && aGlCtx == NULL; --aLowVer3)
{
aCoreCtxAttribs[1] = 3; aCoreCtxAttribs[3] = aLowVer3;
aGlCtx = aCreateCtxProc (theDevCtx, NULL, aCoreCtxAttribs);
}
}
if (aGlCtx != NULL)
{
if (!::wglMakeCurrent (theDevCtx, aGlCtx)) { std::cerr << "Error: unable to bind context\n"; }
}
return aGlCtx;
}
public:
//! Empty constructor.
WglWindow (const wchar_t* theName) : myWin (NULL), myDevCtx (NULL), myGlCtx (NULL) {}
//! Destructor.
~WglWindow() { Release(); }
//! Release resources.
void Release()
{
//wglMakeCurrent (NULL, NULL);
if (myWin != NULL && myDevCtx != NULL) { ::ReleaseDC (myWin, myDevCtx); myDevCtx = NULL; }
if (myGlCtx != NULL) { ::wglDeleteContext (myGlCtx); myGlCtx = NULL; }
if (myWin != NULL) { ::DestroyWindow (myWin); myWin = NULL; }
}
public:
//! Create a window handle.
bool CreateDefaultWindow()
{
myWin = createWglWindow (L"TmpGlWindow");
if (myWin == NULL) { return false; }
myDevCtx = ::GetDC (myWin);
if (myDevCtx == NULL) { return false; }
if (!WglWindow::SetWindowPixelFormat (myDevCtx, -1)) { return false; }
myGlCtx = ::wglCreateContext (myDevCtx);
return myGlCtx != NULL && ::wglMakeCurrent (myDevCtx, myGlCtx);
}
//! Wrapper for SetPixelFormat().
static bool SetWindowPixelFormat (HDC theDevCtx, int theFormat)
{
PIXELFORMATDESCRIPTOR aFormat = {};
aFormat.nSize = sizeof(aFormat);
aFormat.nVersion = 1;
aFormat.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
aFormat.iPixelType = PFD_TYPE_RGBA;
aFormat.cColorBits = 32;
const int aFormatIndex = theFormat == -1 ? ::ChoosePixelFormat (theDevCtx, &aFormat) : theFormat;
if (aFormatIndex == 0)
{
std::cerr << "Error: ChoosePixelFormat() failed, Cannot find a suitable pixel format.\n";
return false;
}
if (theFormat != -1) { ::DescribePixelFormat (theDevCtx, aFormatIndex, sizeof(PIXELFORMATDESCRIPTOR), &aFormat); }
if (::SetPixelFormat (theDevCtx, aFormatIndex, &aFormat) == FALSE)
{
std::cerr << "Error: SetPixelFormat(" << aFormatIndex << ") failed with error code " << GetLastError() << "\n";
return false;
}
return true;
}
public:
//! Dummy window procedure.
static LRESULT WINAPI dummyWinProc (HWND theWin, UINT theMsg, WPARAM theParamW, LPARAM theParamL)
{
return ::DefWindowProcW (theWin, theMsg, theParamW, theParamL);
}
//! Create a window handle.
static HWND createWglWindow (const wchar_t* theTitle)
{
WNDCLASSW aWinClass = {};
aWinClass.lpszClassName = L"OpenGL";
static HINSTANCE anAppInstance = NULL;
if (anAppInstance == NULL)
{
// only register the window class once
anAppInstance = GetModuleHandleW (NULL);
aWinClass.style = CS_OWNDC;
aWinClass.lpfnWndProc = dummyWinProc;
aWinClass.hInstance = anAppInstance;
aWinClass.hIcon = LoadIconW (NULL, IDI_WINLOGO);
aWinClass.hCursor = LoadCursorW (NULL, IDC_ARROW);
if (!RegisterClassW (&aWinClass))
{
std::cerr << "Error: RegisterClass() failed, cannot register window class.\n";
return NULL;
}
}
HWND aWin = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE, aWinClass.lpszClassName, theTitle,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
2, 2, 4, 4, NULL, NULL, anAppInstance, NULL);
if (aWin == NULL) { std::cerr << "Error: CreateWindow() failed, Cannot create a window.\n"; }
return aWin;
}
private:
HWND myWin;
HDC myDevCtx;
HGLRC myGlCtx;
};
int main()
{
HWND aTestWin = WglWindow::createWglWindow (L"GLWindow");
HDC aDevCtx = ::GetDC (aTestWin);
HGLRC aGlCtx = WglWindow::CreateCoreProfile (aDevCtx, false);
if (aGlCtx != NULL)
{
std::cout << "[WGL] OpenGL vendor string: " << ::glGetString (GL_VENDOR) << "\n";
std::cout << "[WGL] OpenGL renderer string: " << ::glGetString (GL_RENDERER) << "\n";
std::cout << "[WGL] OpenGL version string: " << ::glGetString (GL_VERSION) << "\n";
}
return 0;
}
请注意,代码段尝试创建最高4.x或3.x版本的Core Profile(对于这种情况,当引擎是可扩展的,并且希望尽可能地用作匹配功能时),如果仅需要,可以将其省略确切的版本。