C OpenGL: треугольник не отображается на экране

#c #opengl

#c #opengl

Вопрос:

Я следую руководству, чтобы нарисовать треугольник на экране с помощью OpenGL. Я правильно выполнил все шаги, но я получаю только зеленый экран без треугольника.

Это мой текущий код. drawScene вызывается во время инициализации приложения и изменяет размер при каждом WM_DRAW. Мой вопрос: почему треугольник не отображается в моем коде?

Версия OpenGL: 4.6

 #include "glew.h"

GLuint program;
GLuint VAO, VBO, EBO;

void DrawScene(HWND _hWnd);

void SetupShaders()
{
    const char* vertexSource = {
        "#version 130 coren"

        "layout (location = 0) in vec3 iPos;n"

        "void main()n"
        "{n"
        "   gl_Position = vec4(iPos, 1.0f);n"
        "}n"
        ""
    };
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, amp;vertexSource, NULL);
    glCompileShader(vertexShader);

    const char* fragmentSource = {
        "#version 130 coren"

        "out vec4 FragColor;n"

        "void main()n"
        "{n"
        "   FragColor = vec4(1.0f, 0.0f, 1.0f, 1.0f);n"
        "}n"
        ""
    };
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, amp;fragmentSource, NULL);
    glCompileShader(fragmentShader);

    program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glBindAttribLocation(program, 0, "iPos");
    glLinkProgram(program);
}
void SetupBuffers()
{
    glGenVertexArrays(1, amp;VAO);
    glGenBuffers(1, amp;VBO);
    glGenBuffers(1, amp;EBO);

    float vertexData[] = {
        0.0f, 0.0f, 0.0f,
        10.0f, 10.0f, 0.0f,
        10.0f, 0.0f, 0.0f,
        0.0f, 10.0f, 0.0f
    };
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

    unsigned int indexData[] = {
        0, 1, 2,
        1, 2, 3
    };
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(float) * 3, (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

void SetupScene(HWNDamp; _hWnd)
{
    static PIXELFORMATDESCRIPTOR pfd =                  // pfd Tells Windows How We Want Things To Be
    {
        sizeof(PIXELFORMATDESCRIPTOR),                  // Size Of This Pixel Format Descriptor
        1,                              // Version Number
        PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
        PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
        PFD_DOUBLEBUFFER,                       // Must Support Double Buffering
        PFD_TYPE_RGBA,                          // Request An RGBA Format
        32,                               // Select Our 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,                         // Accumulation Bits Ignored
        16,                             // 16Bit Z-Buffer (Depth Buffer)
        0,                              // No Stencil Buffer
        0,                              // No Auxiliary Buffer
        PFD_MAIN_PLANE,                         // Main Drawing Layer
        0,                              // Reserved
    };
    HDC hdc = GetDC(_hWnd);
    int pf = ChoosePixelFormat(hdc, amp;pfd);

    SetPixelFormat(hdc, pf, amp;pfd);
    
    HGLRC hglrc = wglCreateContext(hdc);
    wglMakeCurrent(hdc, hglrc);

    glewInit();

    ShowWindow(_hWnd, SW_SHOW);
    SetForegroundWindow(_hWnd);
    SetFocus(_hWnd);

    SetupShaders();
    SetupBuffers();

}

void ResizeScene(HWNDamp; _hWnd, size_t _width, size_t _height)
{
    if (!_height)
    {
        _height = 1;
    }
    glViewport(0, 0, _width, _height);
    DrawScene(_hWnd);
}

void DrawScene(HWND _hWnd)
{
    HDC hdc = GetDC(_hWnd);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);

    glUseProgram(program);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);

    SwapBuffers(hdc);
}
 

Ответ №1:

Вам действительно нужно включить уровень проверки отладки и проверять ошибки, потому что в вашем коде есть целая куча легко уловимых заблуждений:

  1. Не используйте glBindAttribLocation . iPos уже (правильно) привязан к местоположению макета 0, вы просто нарушаете его.
  2. Вы не отсоединяли и не удаляли свои шейдерные программы после того, как связали программу, что привело к утечке памяти.
  3. Не отсоединяйте буферы вершин и элементов от вашего массива вершин, в этом весь смысл его использования в первую очередь.
  4. Связанный с 3, не меняйте буферы вершин и элементов вашего массива вершин при каждом рендеринге. Вы настраиваете буфер вершин один раз.
  5. Вы сообщаете OpenGL, что ваши элементы индекса являются байтами в вашем glDrawElements , и вместо этого вы загружаете их как 32-разрядные целые числа. Будьте последовательны.

Комментарии:

1. Большое вам спасибо за помощь! Я искал решение в течение нескольких дней

2. Могу ли я также предложить научиться использовать Renderdoc (или аналогичный), в нем есть окно для отображения ошибок / предупреждений, и вы сможете увидеть, правильно ли интерпретируются ваши данные. Это поможет вам диагностировать проблемы, подобные # 5.

3. Ошибки / предупреждения в RenderDoc — это просто вывод уровня отладки, вы можете (и должны) получить это и в своем собственном коде.