glDrawElements在PyOpenGL中绘制一个立方体 [英] glDrawElements to draw a cube in PyOpenGL

查看:60
本文介绍了glDrawElements在PyOpenGL中绘制一个立方体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于有几本教程(尤其是Nicolas P. Rougier的教程),我最近开始通过Python学习OpenGL: http://www.labri.fr/perso/nrougier/teaching/opengl/).

I recently started to learn OpenGL through Python thanks to several tutorial (especially the Nicolas P. Rougier one: http://www.labri.fr/perso/nrougier/teaching/opengl/).

我现在正在切换到3D,并且试图绘制一个立方体.

I am now switching to 3D and I am trying to draw a cube.

因此,我设法获得了一些不渲染立方体的三角形(这似乎很正常,因为我不复制顶点,而是使用glDrawArrays函数).

Thus, I manage to get some triangles which do not render a cube (this seems to be normal as I do not duplicate my vertices and I use the glDrawArrays function).

但是,之后,我建立了一个索引向量",以进一步使用glDrawElements函数来呈现我的多维数据集.结果,我没有收到任何错误,但屏幕上没有任何显示.

However, after, I build an index "vector" to further use the glDrawElements function to render my cube. As a result, I do not get any error but nothing appears on screen.

希望您能对您有所帮助!

I hope you could be of some help!

这是我的代码:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import ctypes
import numpy as np
import OpenGL.GL as gl
import OpenGL.GLUT as glut

vertex_code = """

    uniform float scale;
    uniform mat4 matCam;
    attribute vec4 color;
    attribute vec3 position;
    varying vec4 v_color;
    void main()
    {
        gl_Position = matCam*vec4(scale*position, 1.0);
        v_color = color;
    } """

fragment_code = """
    varying vec4 v_color;
    void main()
    {
        gl_FragColor = v_color;
    } """

def display():
    gl.glClear(gl.GL_COLOR_BUFFER_BIT)
    #gl.glDrawArrays(gl.GL_TRIANGLES, 0, 12)

    gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, index) # render nothing (i.e. only the background color)
    glut.glutSwapBuffers()

def reshape(width,height):
    gl.glViewport(0, 0, width, height)

def keyboard( key, x, y ):
    if key == '\033':
        sys.exit( )

def timer(fps):
    global clock
    clock += 0.0005*1000.0/fps
    print(clock)
#    eye = np.array([0,0,1])
#    center = np.array([0,clock,0])
#    up = np.array([0,1,0])
#    mat = computeLookAtMatrix(eye, center, up)
    theta = clock;
    mat = np.array([[np.cos(theta), 0, np.sin(theta), 0],
                [0, 1, 0, 0],
                [-np.sin(theta), 0, np.cos(theta), 0],
                [0, 0, 0, 1]])
    loc = gl.glGetUniformLocation(program, "matCam")
    gl.glUniformMatrix4fv(loc, 1, False, mat)



    glut.glutTimerFunc(1000/fps, timer, fps)
    glut.glutPostRedisplay()


# GLUT init
# --------------------------------------
glut.glutInit()
glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGBA)
glut.glutCreateWindow('Hello world!')
glut.glutReshapeWindow(512,512)
glut.glutReshapeFunc(reshape)
glut.glutDisplayFunc(display)
glut.glutKeyboardFunc(keyboard)
glut.glutTimerFunc(1000/60, timer, 60)

# Build data
# --------------------------------------
data = np.zeros(8, [("position", np.float32, 3),
                    ("color",    np.float32, 4)])

data['color']    = [ (1,0,0,1), (0,1,0,1), (0,0,1,1), (1,1,0,1),
                    (1,0,0,1), (0,1,0,1), (0,0,1,1), (1,1,0,1) ]

data['position'] = [ (-1,-1,1),
                     (1,-1,1),
                        (1,1,1),   
                        (-1,1,1),
                        (-1,-1,-1),
                        (1,-1,-1),
                        (1,1,-1),
                        (-1,1,-1)]

index = np.array([0,1,2,
                2,3,0,
                1,5,6,
                6,2,1,
                7,6,5,
                5,4,7,
                4,0,3,
                3,7,4,
                4,5,1,
                1,0,4,
                3,2,6,
                6,7,3])

# Build & activate program
# --------------------------------------

# Request a program and shader slots from GPU
program  = gl.glCreateProgram()
vertex   = gl.glCreateShader(gl.GL_VERTEX_SHADER)
fragment = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)

# Set shaders source
gl.glShaderSource(vertex, vertex_code)
gl.glShaderSource(fragment, fragment_code)

# Compile shaders
gl.glCompileShader(vertex)
gl.glCompileShader(fragment)

# Attach shader objects to the program
gl.glAttachShader(program, vertex)
gl.glAttachShader(program, fragment)

# Build program
gl.glLinkProgram(program)

# Get rid of shaders (no more needed)
gl.glDetachShader(program, vertex)
gl.glDetachShader(program, fragment)

# Make program the default program
gl.glUseProgram(program)


# Build buffer
# --------------------------------------

# Request a buffer slot from GPU
buffer = gl.glGenBuffers(1)

# Make this buffer the default one
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)

# Upload data
gl.glBufferData(gl.GL_ARRAY_BUFFER, data.nbytes, data, gl.GL_DYNAMIC_DRAW)

# same for index buffer
buffer_index= gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, buffer_index)
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index, gl.GL_STATIC_DRAW)


# Bind attributes
# --------------------------------------
stride = data.strides[0]
offset = ctypes.c_void_p(0)
loc = gl.glGetAttribLocation(program, "position")
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)

offset = ctypes.c_void_p(data.dtype["position"].itemsize)
loc = gl.glGetAttribLocation(program, "color")
gl.glEnableVertexAttribArray(loc)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
gl.glVertexAttribPointer(loc, 4, gl.GL_FLOAT, False, stride, offset)

gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, buffer_index)

# Bind uniforms
# --------------------------------------
loc = gl.glGetUniformLocation(program, "scale")
gl.glUniform1f(loc, 0.5)
clock = 0

loc = gl.glGetUniformLocation(program, "matCam")
print(loc)
gl.glUniformMatrix4fv(loc, 1, False, np.eye(4))

# Enter mainloop
# --------------------------------------
glut.glutMainLoop()

推荐答案

gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, index)

根据是否绑定ELEMENT_ARRAY_BUFFER,index参数具有两种不同的含义:

The index argument has two different meanings depending on whether an ELEMENT_ARRAY_BUFFER is bound or not:

  • 如果没有限制:则它指定一个指向存储索引的客户端内存的指针
  • 如果绑定了ELEMENT_ARRAY_BUFFER,则index参数指定此缓冲区的偏移量.这定义了索引在缓冲区中的起始位置.
  • If no bound: Then it specifies a pointer to client memory where the indices are stored
  • If a ELEMENT_ARRAY_BUFFER is bound, then the index parameter specifies an offset into this buffer. This defines where in the buffer the indices start.

在您的情况下,绑定了缓冲区,因此您告诉OpenGL从缓冲区中的某个位置开始.但是,您想要的是从缓冲区的开头开始,因此必须将index设置为0.

In your case, a buffer is bound, so you tell OpenGL to start somewhere in the buffer. But what you want is to start at the beginning of the buffer, thus you have to set index to 0.

gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, ctypes.c_void_p(0))

这篇关于glDrawElements在PyOpenGL中绘制一个立方体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆