我刚刚查看了我为 Windows 所做的源代码。由于这是对生产代码的研究(因此使用了我们生产代码的其他内容),我无法按原样提供它。我在这里展示的是一个精简版本,它应该显示它是如何工作的:
// standard C/C++ header:
#include <iostream>
// Windows header:
#include <Windows.h>
using namespace std;
int main(int argc, char **argv)
{
if (argc < 3) {
cerr << "USAGE: " << argv[0]
<< " FILE [FILES...] IMG_FILE" << endl;
return -1;
}
// Import Scene Graph
// excluded: initialize importers
// excluded: import 3d files
#ifdef _WIN32
// Window Setup
// set window properties
enum { Width = 1024, Height = 768 };
WNDCLASSEX wndClass; memset(&wndClass, 0, sizeof wndClass);
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wndClass.lpfnWndProc = &DefWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = 0;
wndClass.hIcon = 0;
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = 0;
wndClass.lpszClassName = "WndClass";
wndClass.hIconSm = 0;
RegisterClassEx(&wndClass);
// style the window and remove the caption bar (WS_POPUP)
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
// Create the window. Position and size it.
HWND hwnd = CreateWindowEx(0,
"WndClass",
"",
style,
CW_USEDEFAULT, CW_USEDEFAULT, Width, Height,
0, 0, 0, 0);
HDC hdc = GetDC(hwnd);
// Windows OpenGL Setup
PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof pfd);
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 16;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
// get the best available match of pixel format for the device context
int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
// make that the pixel format of the device context
SetPixelFormat(hdc, iPixelFormat, &pfd);
// create the context
HGLRC hGLRC = wglCreateContext(hdc);
wglMakeCurrent(hdc, hGLRC);
#endif // _WIN32
// OpenGL Rendering Setup
/* excluded: init our private OpenGL binding as
* the Microsoft API for OpenGL is stuck <= OpenGL 2.0
*/
// create Render Buffer Object (RBO) for colors
GLuint rboColor = 0;
glGenRenderbuffers(1, &rboColor);
glBindRenderbuffer(GL_RENDERBUFFER, rboColor);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create Render Buffer Object (RBO) for depth
GLuint rboDepth = 0;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create Frame Buffer Object (FBO)
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// attach RBO to FBO
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, rboColor);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rboDepth);
// GL Rendering Setup
// excluded: prepare our GL renderer
glViewport(0, 0, Width, Height);
glClearColor(0.525f, 0.733f, 0.851f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
/* compute projection matrix from
* - field of view (property fov)
* - aspect ratio of view
* - near/far clip distance (properties dNear and dFar).
*/
const DegreeD fov(30.0);
const double dNear = 0.1, dFar = 100.0;
const double ar = (float)Width / Height;
const double d = ::tan(fov / 2.0) * 2.0 * dNear;
// excluded: construct a projection matrix for perspective view
// excluded: determine bounding sphere of 3D scene
// excluded: compute camera and view matrix from the bounding sphere of scene
// excluded: OpenGL rendering of 3d scene
// read image from render buffer
// excluded: prepare image object to store read-back
//Image::Object img(4, Image::BottomToTop);
//img.set(Width, Height, Image::RGB24);
//const size_t bytesPerLine = (3 * Width * 4 + 3) / 4;
//glReadPixels(0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, img.getData());
// store image
const string filePath = argv[argc - 1];
// excluded: export image in a supported image file format
// clean-up
// excluded: clean-up of 3D scene (incl. OpenGL rendering add-ons)
glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rboColor);
glDeleteRenderbuffers(1, &rboDepth);
#ifdef _WIN32
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hGLRC);
#endif // _WIN32
// done
return 0;
}
我没有检查这是否可以编译(如上所述)。它被从我这边在 Windows 10 上编译和运行的代码中删除。
关于 OpenGL 和 Windows 的注意事项:
我自己进行了 GL 绑定,因为 Microsoft Windows OpenGL API 不支持 OpenGL 3.0 或更高版本。 (我可以使用像这样的库glfw)这意味着我必须将函数地址分配给函数指针(以更正函数原型),以便我可以使用 C 函数调用正确地调用 OpenGL 函数。
授予功能的可用性if我安装了适当的硬件和适当的驱动程序。 (可以检查驱动程序是否提供某些功能。)
如果此类绑定函数调用失败(例如,出现分段错误),可能的原因可能是:
被调用函数的签名错误。 (我使用从 khronos.org 下载的标头来授予正确的原型。希望驱动程序提供商也这样做。)
该函数在驱动程序中不存在。 (我使用的函数是已安装驱动程序支持的 OpenGL 标准的一部分。该驱动程序支持 OpenGL 4.x,但我只需要 OpenGL 3.x(至少到目前为止)。)
在使用函数指针之前必须对其进行初始化。 (我已经编写了一个未在代码中公开的初始化。这是我放置注释的地方/* excluded: init our private OpenGL binding as the Microsoft API for OpenGL is stuck <= OpenGL 2.0 */
.
为了说明这一点,一些代码示例:
在我的 OpenGL 初始化函数中,我执行以下操作:
glGenFramebuffers
= (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress(
"glGenFramebuffers");
标题提供:
extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
PFNGLGENFRAMEBUFFERSPROC
由提供glext.h
我从下载kronos.org:
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
wglGetProcAddress()由 Microsoft Windows API 提供。
A Note about OpenGL and Linux:
If H/W and the installed driver supports the desired OpenGL standard, functions can be used as usual by
including the necessary headers (e.g. #include <GL/gl.h>)
linking the necessary libraries (e.g. -lGL -lGLU
).
德哈斯评论道:
绝对不能保证 GL 3.x 函数可以通过任何方式导出libGL.so
一个正在使用,即使它们被导出,也不能保证该功能受到支持(即,mesa 对所有驱动程序后端使用相同的前端库,但每个驱动程序可能只支持功能的子集)。您必须在两个平台上使用扩展机制。
我无法提供如何处理此问题的简单建议,也没有宝贵的实践经验。所以,我想至少提供我通过谷歌搜索找到的这些链接(来自 khronos.org):
加载 OpenGL 函数
OpenGL上下文
OpenGL加载库.