C++ 创建基本的OpenGl上下文
我正在阅读OpenGl红皮书,我几乎被第一个教程困住了。如果我使用freeglut和glew,一切都很好,但我想自己处理输入之类的事情。所以我抛弃了freeglut和glew,编写了自己的代码。我看了一些其他教程并完成了代码,但没有显示任何内容。看起来FreeGlut在背景中使用了一些巫毒魔法,但我不知道我错过了什么。我试过这个:C++ 创建基本的OpenGl上下文,c++,c,windows,opengl,graphicscontext,C++,C,Windows,Opengl,Graphicscontext,我正在阅读OpenGl红皮书,我几乎被第一个教程困住了。如果我使用freeglut和glew,一切都很好,但我想自己处理输入之类的事情。所以我抛弃了freeglut和glew,编写了自己的代码。我看了一些其他教程并完成了代码,但没有显示任何内容。看起来FreeGlut在背景中使用了一些巫毒魔法,但我不知道我错过了什么。我试过这个: int attributeListInt[19]; int pixelFormat[1]; unsigned int formatCount; int result;
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上下文并不是件小事。特别是如果您想使用
wglchoospexelformatarb
,它必须通过OpenGL扩展机制加载…首先需要一个正常工作的OpenGL上下文。我想你会发现这是一个鸡和蛋的问题。此外,用于创建OpenGL上下文的窗口需要某些属性才能可靠地工作。例如,WndClass应该设置CS_OWNDC样式,窗口样式应该包括WS_CLIPSIBLINGS|WS_CLIPCHILDREN
最近,我用我的小型wglarb
helper工具处理了上述鸡和蛋的问题:
它还附带一个小测试程序,演示如何使用它
我建议您使用它提供的功能。我以某种方式编写了这个小助手库,如果您的程序使用其他扩展加载机制,它不会受到负面影响。但是它还不是线程安全的;我最终不得不补充一点。我花时间使代码线程安全。您现在可以使用公开的函数,而不必关心同步;这一切都是以可靠的方式在内部完成的。首先,三角形是逆时针方向缠绕的,前面是顺时针方向。通过剔除背面(逆时针方向),你不会看到任何东西。要么将正面改为CCW,要么剔除正面,要么禁用剔除。@AndonM.Coleman我已经将其改为CCW,但它仍然没有显示任何内容。我不认为自己做每件事都是一个特别好的解决方案。这样学习不会更快。此外,您有一个双缓冲上下文,但不是swpapping缓冲区(这是必需的,隐式调用
glFlush(…)
或glFinish(…)
,具体取决于您使用的是硬件ICD还是GDI),而是调用了glFlush(…)
。将其替换为SwapBuffers()
,并将GL|u DEPTH_BUFFER_BIT
添加到glClear(…)
调用中(因为您有像素格式的深度缓冲区)。您不必清除深度缓冲区,因为深度测试在默认情况下是禁用的,但是如果启用深度测试,那么事情将开始写入深度缓冲区。@AndonM.Coleman我已禁用深度缓冲区,使用SwapBuffers,现在一切正常,谢谢!