在PyOpenGL中缓冲顶点数据

时间:2016-01-27 18:40:28

标签: pyopengl

我过去一直使用(现代:OpenGL 3.3)OpenGL与C ++绑定。我刚开始学习使用python绑定。我有一个程序运行,但我无法得到任何东西。

我在Windows 10系统上使用64位python 3.4。

它应该画一个三角形。如果我使用GL_POINTS绘制,我可以在屏幕的中心得到一个点,使用GL_TRIANGLES,我什么也得不到。

我认为问题在于我如何缓冲数据。我不认为python正在发送我认为它正在发送的东西,因为C ++和python之间的内存管理存在差异(我可能完全错了,也可能是其他东西)。

data应该是指向包含顶点数据的连续内存块的指针。我不确定如何在python中实现这一点(或者即使这是在pyopengl中应该如何实现的)。

这是我用来生成顶点位置数据并将其发送到OpenGL的代码:

# Define some data, we will be drawing a triangle
vertices = [-1.0, -1.0,  0.0,
             0.0, +1.0,  0.0,
            +1.0, -1.0,  0.0]

data = (gl.GLfloat * len(vertices))(*vertices)

vertex_array_object = gl.glGenVertexArrays(1)
gl.glBindVertexArray(vertex_array_object)

gl.glUseProgram(program)

# Create a buffer object
buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, (4*8)*3*3, data, gl.GL_STATIC_DRAW)     

gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, ctypes.c_void_p(0))

# Unbind the VAO
gl.glBindVertexArray(0)

我想要一个不使用numpy的解决方案。我的目标是Windows平台,我得到的所有建议(和经验)是numpy与windows不兼容(没有简单的构建方式;安装程序有缺陷等)。

这是完整的程序。注意:它需要运行GLFW dll(对于Windows,它们可以在http://www.glfw.org/download.html处获得)

import OpenGL.GL as gl          #OpenGL
from pyglfw.libapi import *     # Window Toolkit - GLFW (Python libapi version)
import struct
import ctypes

glfwInit()

print(glfwGetVersion())

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

width = 600
height = 480
window = glfwCreateWindow(width, height, b'Hello GLFW (libapi)', None, None)

glfwMakeContextCurrent(window)

glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, gl.GL_TRUE)

def load_shaders():    
    program  = gl.glCreateProgram()

    vertex_shader   = gl.glCreateShader(gl.GL_VERTEX_SHADER)
    fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)

    shader_file = open('VertexShader.glsl', 'r')        # open the file for reading
    vertex_shader_code = shader_file.read()             # read the whole file
    shader_file.close()                                 # close the file
    gl.glShaderSource(vertex_shader, vertex_shader_code)       # make that the source code

    shader_file = open('FragmentShader.glsl', 'r')
    fragment_shader_code = shader_file.read()
    gl.glShaderSource(fragment_shader, fragment_shader_code)
    shader_file.close()

    # Compile shaders
    gl.glCompileShader(vertex_shader)
    if gl.glGetShaderiv(vertex_shader, gl.GL_COMPILE_STATUS) != gl.GL_TRUE:    # Check if compilation was successful
        info_log = gl.glGetShaderInfoLog(vertex_shader)
        raise RuntimeError('Vertex shader compilation failed: %s' % (info_log))
    else:
        print('Vertex shader compiled successfuly')

    gl.glCompileShader(fragment_shader)
    if gl.glGetShaderiv(fragment_shader, gl.GL_COMPILE_STATUS) != gl.GL_TRUE:    # Check if compilation was successful
        info_log = gl.glGetShaderInfoLog(fragment_shader)
        raise RuntimeError('Fragment shader compilation failed: %s' % (info_log))
    else:
        print('Fragment shader compiled successfuly')

    gl.glAttachShader(program, vertex_shader)
    gl.glAttachShader(program, fragment_shader)

    gl.glLinkProgram(program)

    gl.glDetachShader(program, vertex_shader)
    gl.glDetachShader(program, fragment_shader)

    return program

#dark blue background
gl.glClearColor(0.0, 0.0, 0.4, 0.0);

# Get our shader program
program = load_shaders()

# Define some data, we will be drawing a triangle
vertices = [-1.0, -1.0,  0.0,
             0.0, +1.0,  0.0,
            +1.0, -1.0,  0.0]

data = (gl.GLfloat * len(vertices))(*vertices)

vertex_array_object = gl.glGenVertexArrays(1)
gl.glBindVertexArray(vertex_array_object)

gl.glUseProgram(program)

# Create a buffer object
buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glBufferData(gl.GL_ARRAY_BUFFER, (4*8)*3*3, data, gl.GL_STATIC_DRAW)     

gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, ctypes.c_void_p(0))

# Unbind the VAO
gl.glBindVertexArray(0)

while True:
    # Check the exit condition
    if glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS:
        break

    # Clear the screen
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);

    # Draw our triangle
    gl.glBindVertexArray(vertex_array_object)
    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)         #Starting from vertex 0, draw 3 vertices total -> 1 triangle
    gl.glBindVertexArray(0)

    glfwSwapBuffers(window)
    glfwPollEvents()

glfwTerminate()

顶点着色器:

#version 330 core

layout(location = 0) in vec3 position;

void main()
{
    gl_Position = vec4(position, 1.0);
}

片段着色器:

#version 330

void main()
{
    gl_FragColor.rgb = vec3(1.0, 0.0, 0.0);
    gl_FragColor.a = 0.8;
}

0 个答案:

没有答案