发布于 2021-11-04 13:51:55
OpenGL只是一个标准。我认为OpenGL Khronos组只为OpenGL实现提供了头部,而没有提供其他任何内容。图形卡供应商为其图形卡提供了一个驱动程序,该驱动程序被链接到操作系统内核中。这里的问题是你不知道司机是怎么工作的。因此,供应商必须提供用户模式库及其驱动程序,以便软件实现者能够驱动卡。这通常以OpenGL/Direct3D实现的形式出现,其形式是可以从用户模式程序中链接的用户模式库。
而且,我不是专家,但我可以看出,您需要创建一个OpenGL上下文,并将该上下文与平台相关的上下文联系起来,该上下文是呈现内容的实际窗口。这意味着,当线程执行OpenGL命令时,您需要告诉操作系统在哪里绘制。否则,您的OpenGL命令/代码行不会执行任何操作,因为它们没有与窗口/设备上下文链接。
例如,在Linux上,您有一个名为/dev/dri/ card 0的文件,它是基于Intel/AMD的计算机上的集成显卡。OpenGL库实现将在此字符设备上以ioctl()调用的形式执行系统调用,以驱动卡。在下面,有一个驱动程序是由硬件供应商提供的,它在内核中注册自己,并告诉具有某些功能的内核,这个驱动程序是一个图形驱动程序,它支持某些类型的设备,其中包括/dev/dri/card0 0字符设备。它还可能传递一个PCI ID,这是图形卡读取其PCI配置空间时返回的设备ID。因此,操作系统内核能够识别该驱动程序必须用于某个字符设备,因为该设备具有与注册时提供的ID相同的ID。
有一些图书馆,如过剩,免费和GLFW,这些都是非常糟糕的。它们通常不起作用,而且很难使用,因为它们最终往往会产生大量的链接问题,而一个符合这个名称的游戏/3D开发人员不会使用它们。这些库只提供窗口和用户输入功能。因此,在使用X服务器在Linux上创建窗口和获取用户输入的意义上,这些库是非常无用的,而在Windows上的等效代码是1行代码,这称为窗口的过程。它真的很简单,可以自己实现。实际上,这些图书馆(freeglut,GLFW等)使用操作系统内核开发人员提供的依赖于平台的API。它们只在一些#ifdef (宏)中包装,以提供跨平台功能。最后,复制这些库所做的工作是微不足道的,而且通常比实际使用这些库更好。
此外,Windows只提供OpenGL 1.1的开箱即用支持。因此,您可以在中方便地使用和定义这些函数。您可以看到,这些函数是棕色高亮显示的,当您将鼠标悬停在顶部时,您可以看到函数的签名。GLEW (而不是GLFW)库对于初学者(像我一样)能够在1.1以上的OpenGL中开始编码而不需要更多的工作是非常有用的。GLEW库将测试OpenGL函数的存在,并在Windows上使用GetProcAdress()或wglGetProcAddress()获取过程地址,这是跨平台的(更多信息在这里:函数)。这个库需要一个名为glw32.lib的静态.lib文件、一个名为.dll (放在可执行文件的目录中)的.dll和一个在您的程序中包含的名为glw.h的头。现在我不会告诉您如何将包含目录和库目录添加到Visual中,但是您可以在Google的某个地方查看一下。GLEW提供的OpenGL函数将以宏的形式出现。您将在中看到它们是紫色的。
例如,使用OpenGL和Visual在Windows上执行与GLFW相同的简单WinAPI程序如下:
#include <windows.h>
#include <glew.h>
#include <gl/GL.h>
#include <iostream>
#pragma comment(lib, "glew32")
#pragma comment(lib, "opengl32")
#pragma comment(lib, "glu32")
HDC dc;
HGLRC rc;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg)
{
case WM_PAINT:
{
}
break;
case WM_LBUTTONDOWN:
{
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
break;
}
}
int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"Window";
RegisterClass(&wc);
HWND hwnd = CreateWindowExW(0, L"Window", L"Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
AllocConsole();
freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
MSG msg = { };
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
dc = GetDC(hwnd);
int index;
index = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, index, &pfd);
rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
GLenum res = glewInit();
if (res != GLEW_OK) {
printf("GLEW init failed: %s!", glewGetErrorString(res));
}
else {
printf("GLEW init success!\n");
}
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers(dc);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}这个程序应该创建一个空白窗口,创建一个控制台,打印"GLEW init sucess!“在控制台上,然后使窗口的背景变为黑色。您可以看到,这段代码非常琐碎,这就是GLFW在其“跨平台”API下所做的事情。就像我说的,我是个初学者,但我认为,在这种情况下,OpenGL调用将写入一个双缓冲区,因为我们启用了像素格式结构的双缓冲。要在屏幕上实际呈现某些内容,需要使用窗口的dc调用SwapBuffers(),用实际绘制的主缓冲区交换双缓冲区。
发布于 2015-06-06 18:33:27
OpenGL是一个开放的标准。最新版本取决于您为GPU安装的驱动程序。
要使用高于1.1的opengl,您需要glew (它公开了驱动程序支持的功能)和上下文创建框架:
GLFW,过剩,SDL
还有更多。
目前最新的OpenGL实现: 4.5
发布于 2015-06-06 19:43:09
Windows没有更新的SDK1.1,只提供了gl.h for OpenGL 1.1。若要在窗口OpenGL中使用其他功能,必须使用扩展头glext.h。这可以从Khronos获得,并在新的扩展可用时进行更新。您可以使用wglGetProcAddress获取函数指针,以便在GL (或扩展)的以后版本中可用。访问附加功能的过程因平台而异。例如,如果使用X11,可以使用glXGetProcAddressARB,如果平台上有EGL,则可以使用eglGetProcAddress。
根据平台和SDK的不同,如果平台提供了更新的GL,在包含glext.h之前,您也可以简单地使用该平台。显然,由于Windows没有提供更新的SDK,所以这是不可能的,但它是在Linux、Mac、iOS和Android上。在这两种方法中,您都需要确保所使用的GL上下文要么支持核心API中的函数,要么支持提供该函数的扩展(请参阅glGetString with GL_EXTENSIONS),但您用它构建的SDK包含该功能是不够的。因此,使用“运行时链接”glGetProcAddress方法更安全,因为如果函数不可用,它将只返回NULL。使用不可用的函数将导致未定义的行为,并可能崩溃。
至于在任何给定平台上支持的最新版本,这取决于您的视频驱动程序,而不是您使用的SDK。创建OpenGL上下文时,glGetString w/GL_VERSION将指示您的上下文支持哪个版本的OpenGL,而不管使用哪个版本的GL构建。您可以使用版本保证的任何功能,以及报告的扩展提供的任何功能。
https://stackoverflow.com/questions/30685887
复制相似问题