OpengL Где мой квадрат?

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

Я слежу за учебными пособиями на веб-сайте Learnopengl.com по python, поэтому это немного добавляет головной боли. Любая идея, почему это не работает? Я смотрю на это почти день и не вижу ошибки на своем пути.

import glfw
import numpy as np
import OpenGL

from OpenGL.GL import *
from OpenGL.GL import shaders, ArrayDatatype
from ctypes import sizeof, c_float, c_void_p

def main():
    width = 800
    height = 600
    title = 'Hello Triangle'

    vertex = """#version 410 core
        in vec3 aPos;
        void main() {
            gl_Position = vec4(aPos, 1.0);
        }"""
    fragment = """#version 410 core
        out vec4 FragColor;
        void main() {
            FragColor = vec4(1.0, 0.5, 0.2, 1.0);
        }"""

    if not glfw.init():
        raise TypeError('Unable to initalize glfw')

    glfw.window_hint(glfw.SAMPLES, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    glfw.window_hint(glfw.OPENGL_DEBUG_CONTEXT, True)

    window = glfw.create_window(width, height, title, None, None)
    if not window:
        raise TypeError('Unable to create the window')
    glfw.make_context_current(window)
    glfw.set_framebuffer_size_callback(window, framebuffer_size)

    verts = np.array([[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]], dtype=np.float)
    indices = np.array([[0, 1, 3], [3, 1, 2]], dtype=np.uint)

    vertex_shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader, vertex)
    glCompileShader(vertex_shader)

    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader, fragment)
    glCompileShader(fragment_shader)

    shader_program = glCreateProgram()
    glAttachShader(shader_program, vertex_shader)
    glAttachShader(shader_program, fragment_shader)
    glLinkProgram(shader_program)

    glDeleteShader(vertex_shader)
    glDeleteShader(fragment_shader)

    vao_id = glGenVertexArrays(1)
    vbo_id = glGenBuffers(1)
    ebo_id = glGenBuffers(1)

    glBindVertexArray(vao_id)

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_id)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)
    #glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

    glBindBuffer(GL_ARRAY_BUFFER, vbo_id)
    glBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW)
    glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)
    glEnableVertexAttribArray(0)

    #glBindBuffer(GL_ARRAY_BUFFER, 0)

    #glBindVertexArray(0)

    while not glfw.window_should_close(window):
        glClearColor(0.2, 0.3, 0.3, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)

        glUseProgram(shader_program)
        glBindVertexArray(vao_id)
        glEnableVertexAttribArray(0)
        #glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
        glBindVertexArray(0)

        glfw.swap_interval(1)
        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

def framebuffer_size(window, width, height):
    glViewport(0, 0, width, height)


if __name__ == '__main__':
    main()

person Adam Adam Adam    schedule 01.04.2018    source источник


Ответы (1)


В этом коде необходимо решить две сложные проблемы, и обе они тонкие и специфичные для Python.

Во-первых, вы должны заменить 0 в glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0) на None. Я подозреваю, что это связано с тем, что PyOpenGL использует ctypes для переноса OpenGL, а None рекомендуется представлять указатель NULL в соответствии с документация ctypes. Если вам нужно использовать смещения для ваших буферов позже, вы должны посмотреть этот ответ.

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

введите здесь описание изображения

Что случилось с нашим оранжевым прямоугольником? Что ж, проблема здесь в данных, которые мы передаем нашим буферным объектам. Если вы используете 64-битное устройство, типы данных numpy (dtype) также будут 64-битными, если они не указаны полностью. OpenGL ожидает 32-битные числа с плавающей запятой и целые числа, а не удвоения, поэтому вместо этого нам нужно использовать np.float32. Я бы также использовал np.uint32 для вашего индексного буфера для согласованности, но это не является строго необходимым. Если мы исправим ваши операторы инициализации verts и indices следующим образом:

verts = np.array([[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]], dtype=np.float32)
indices = np.array([[0, 1, 3], [3, 1, 2]], dtype=np.uint32)

Результаты должны быть больше похожи на то, что вы ожидаете:

введите здесь описание изображения

Надеюсь это поможет!

person CodeSurgeon    schedule 01.04.2018
comment
@AdamAdamAdam Рад, что это помогло. Если вы пройдете все эти учебные пособия по opengl, может быть, вы сможете разместить весь окончательный код на github для каждого учебника, если у вас будет такая возможность? Я подозреваю, что это будет полезно для других, которые, вероятно, столкнутся с подобными проблемами (я знаю, что определенно столкнулся с этим в первый раз). - person CodeSurgeon; 01.04.2018
comment
Это было моим намерением. Пройдите все сложные части и разместите код на github. - person Adam Adam Adam; 01.04.2018