0

私は OpenGl の赤い本を読んでいますが、最初のチュートリアルでほとんど立ち往生しています。freeglut と glew を使えばすべて問題なく動作しますが、入力などは自分で処理したいと考えています。そこで、freeglut と glew を捨てて、独自のコードを書きました。他のチュートリアルをいくつか見てコードを完成させましたが、何も表示されません。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;
}
4

1 に答える 1

0

OpenGL コンテキストの作成は簡単ではありません。特に、OpenGL 拡張メカニズムを介してロードする必要があるものを使用したい場合wglChoosePixelFormatARBは、最初に機能する OpenGL コンテキストが必要です。これは鶏が先か卵が先かという問題だということがお分かりいただけたと思います。さらに、OpenGL コンテキストの作成に使用する Window には、確実に機能するために特定の属性が必要です。1 つは、WndClass に CS_OWNDC スタイルを設定し、ウィンドウ スタイルに含める必要があります。WS_CLIPSIBLINGS | WS_CLIPCHILDREN

私は最近、小さなwglarbヘルパー ツールを使用して前述のニワトリが先か卵が先かという問題に取り組みました: https://github.com/datenwolf/wglarb

また、使用方法を示す小さなテスト プログラムも付属しています。

それによって提供される機能を使用することをお勧めします。この小さなヘルパー ライブラリは、プログラムが他の拡張機能の読み込みメカニズムを使用しても悪影響を受けないように作成しました。ただし、まだスレッドセーフではありません。私は最終的にそれを追加する必要があります。コードをスレッドセーフにするのに時間をかけました。同期を気にせずに公開された関数を使用できるようになりました。それはすべて、信頼できる方法で内部的に行われます。

于 2014-06-01T21:51:40.550 に答える