创建一个基本的OpenGl上下文

Creating a basic OpenGl context

本文关键字:OpenGl 上下文 一个 创建      更新时间:2023-10-16

我正在阅读OpenGl红皮书,我几乎被第一个教程卡住了。如果我使用freeglut和glow,一切都很好,但我想自己处理输入等问题。所以我放弃了freeglut和glow,自己写代码。我看了其他一些教程并完成了代码,但没有显示任何内容。似乎FreeGlut在后台施了一些巫术,但我不知道我错过了什么。我试过了:

int attributeListInt[19];
int pixelFormat[1];
unsigned int formatCount;
int result;
PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
int attributeList[5];
context = GetDC (hwnd);
if (!context)
    return -1;
attributeListInt[0] = WGL_SUPPORT_OPENGL_ARB;
attributeListInt[1] = TRUE;
attributeListInt[2] = WGL_DRAW_TO_WINDOW_ARB;
attributeListInt[3] = TRUE;
attributeListInt[4] = WGL_ACCELERATION_ARB;
attributeListInt[5] = WGL_FULL_ACCELERATION_ARB;
attributeListInt[6] = WGL_COLOR_BITS_ARB;
attributeListInt[7] = 24;
attributeListInt[8] = WGL_DEPTH_BITS_ARB;
attributeListInt[9] = 24;
attributeListInt[10] = WGL_DOUBLE_BUFFER_ARB;
attributeListInt[11] = TRUE;
attributeListInt[12] = WGL_SWAP_METHOD_ARB;
attributeListInt[13] = WGL_SWAP_EXCHANGE_ARB;
attributeListInt[14] = WGL_PIXEL_TYPE_ARB;
attributeListInt[15] = WGL_TYPE_RGBA_ARB;
attributeListInt[16] = WGL_STENCIL_BITS_ARB;
attributeListInt[17] = 8;
attributeListInt[18] = 0;
result = wglChoosePixelFormatARB (context, attributeListInt, NULL, 1, pixelFormat, &formatCount);
if (result != 1)
    return -1;
result = SetPixelFormat (context, pixelFormat[0], &pixelFormatDescriptor);
if (result != 1)
    return -1;
attributeList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
attributeList[1] = 4;
attributeList[2] = WGL_CONTEXT_MINOR_VERSION_ARB;
attributeList[3] = 2;
attributeList[4] = 0;
rendercontext = wglCreateContextAttribsARB (context, 0, attributeList);
if (rendercontext == NULL)
    return -1;
result = wglMakeCurrent (context, rendercontext);
if (result != 1)
    return -1;
glClearDepth (1.0f);
glFrontFace (GL_CCW);
glEnable (GL_CULL_FACE);
glCullFace (GL_BACK);
return 0;

这设置了一个图形上下文,但显然不足以使一切工作。教程没有包括任何关于视图或投影矩阵,所以我不确定我是否应该添加类似的东西。但是窗口仍然是黑色的。

这是教程代码,调整为我的代码:

#define BUFFER_OFFSET(offset) ((void *)(offset))
bool init ();
bool mainloop ();
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
int main (int argc, char** argv)
{
    Window w;
    w.init (&mainloop);
    if (!init ())
        return 0;
    w.run ();
    w.shutdown ();
    return 0;
}
bool init ()
{
    glGenVertexArrays (NumVAOs, VAOs);
    glBindVertexArray (VAOs[Triangles]);
    GLfloat vertices[NumVertices][2] = {
        {-0.90f, -0.90f}, // Triangle 1
        {0.85f, -0.90f},
        {-0.90f, 0.85f},
        {0.90f, -0.85f}, // Triangle 2
        {0.90f, 0.90f},
        {-0.85f, 0.90f}
    };
    glGenBuffers (NumBuffers, Buffers);
    glBindBuffer (GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData (GL_ARRAY_BUFFER, sizeof(vertices),
        vertices, GL_STATIC_DRAW);
    ShaderInfo shaders[] = {
        {GL_VERTEX_SHADER, "triangles.vert"},
        {GL_FRAGMENT_SHADER, "triangles.frag"},
        {GL_NONE, NULL}
    };
    GLuint program = LoadShaders (shaders);
    glUseProgram (program);
    glVertexAttribPointer (vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (0));
    glEnableVertexAttribArray (vPosition);
    return true;
}
bool mainloop ()
{
    glClear (GL_COLOR_BUFFER_BIT);
    glBindVertexArray (VAOs[Triangles]);
    glDrawArrays (GL_TRIANGLES, 0, NumVertices);
    glFlush ();
    return true;
}

创建OpenGL上下文并不简单。特别是如果你想使用wglChoosePixelFormatARB,它必须通过OpenGL扩展机制加载,这首先需要一个有效的OpenGL上下文来工作。我认为这是一个鸡生蛋还是蛋生鸡的问题。此外,用于创建OpenGL上下文的窗口需要某些属性才能可靠地工作。首先,WndClass应该有CS_OWNDC样式集,窗口样式应该包括WS_CLIPSIBLINGS | WS_CLIPCHILDREN

我最近用我的小wglarb辅助工具解决了前面提到的鸡和蛋的问题:https://github.com/datenwolf/wglarb

它还附带了一个小测试程序,演示如何使用它。

我建议你使用它提供的函数。我编写这个小助手库的方式是,如果您的程序使用其他扩展加载机制,它不会受到负面影响。但是它还不是线程安全的;我最后还是要加上这个。我花时间使代码线程安全。现在你可以使用暴露的函数而不必关心同步;