import textwrap
import numpy as np
from ctypes import *
from OpenGL.GL import *
from OpenGL.GL.ARB.multitexture import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
class TestOpenglManager():
# -------- Magic functions --------
def __init__(self):
self.window_width = 800
self.window_height = 800
# -------- Glut stuff --------
def reshape(self, w, h):
self.window_width = w
self.window_height = h
def animate(self):
glutPostRedisplay()
def visible(self, vis):
if (vis == GLUT_VISIBLE):
glutIdleFunc(self.animate)
else:
glutIdleFunc(0)
def key_pressed(self, *args):
if args[0] == b"\x1b":
sys.exit()
def run(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowSize(self.window_width, self.window_height)
glutInitWindowPosition(800, 100)
glutCreateWindow(b'Test')
glutDisplayFunc(self.display)
glutReshapeFunc(self.reshape)
glutIdleFunc(self.animate)
glutVisibilityFunc(self.visible)
glutKeyboardFunc(self.key_pressed)
self.init()
glutMainLoop()
# -------- Resource allocation --------
def init_shaders(self):
def make_vs(source):
vs = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vs, source)
glCompileShader(vs)
result = glGetShaderiv(vs, GL_COMPILE_STATUS)
if not(result):
raise Exception("Error: {0}".format(
glGetShaderInfoLog(vs)
))
return vs
def make_fs(source):
fs = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fs, source)
glCompileShader(fs)
result = glGetShaderiv(fs, GL_COMPILE_STATUS)
if not(result):
raise Exception("Error: {0}".format(
glGetShaderInfoLog(fs)
))
return fs
def make_program(vs, fs):
program = glCreateProgram()
glAttachShader(program, vs)
glAttachShader(program, fs)
glLinkProgram(program)
return program
vs = textwrap.dedent("""
#version 130
in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0f);
}
""")
fs = textwrap.dedent("""
#version 130
out vec4 frag_color;
uniform vec3 color;
void main() {
frag_color = vec4(color,1.0);
}
""")
self.prog = make_program(make_vs(vs), make_fs(fs))
def init_vbos(self):
vertices = np.array([
# Positions
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,
1, 2, 3
], dtype=np.int32)
vao_id = glGenVertexArrays(1)
vbo_id = glGenBuffers(1)
ebo_id = glGenBuffers(1)
glBindVertexArray(vao_id)
print("Vertices: Uploading {0} bytes".format(
ArrayDatatype.arrayByteCount(vertices)))
glBindBuffer(GL_ARRAY_BUFFER, vbo_id)
glBufferData(
GL_ARRAY_BUFFER,
ArrayDatatype.arrayByteCount(vertices),
vertices, GL_STATIC_DRAW
)
print("Indices: Uploading {0} bytes".format(
ArrayDatatype.arrayByteCount(indices)))
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_id)
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
ArrayDatatype.arrayByteCount(indices),
indices, GL_STATIC_DRAW
)
print("Position: Location {0}".format(
glGetAttribLocation(self.prog, "position")))
vertex_stride = 3
glEnableVertexAttribArray(glGetAttribLocation(self.prog, "position"))
glVertexAttribPointer(glGetAttribLocation(self.prog, "position"),
3, GL_FLOAT, GL_FALSE, vertex_stride, c_void_p(0)
)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
self.obj_metadata = {
"vao_id": vao_id,
"vbo_id": vbo_id,
"ebo_id": ebo_id,
"type": "3v3c3t",
"stride": vertex_stride,
"indices": len(indices),
"vertices": vertices,
"num_triangles": int(len(vertices) / vertex_stride),
"num_vertices": len(vertices)
}
def init(self):
glClearColor(0.0, 0.0, 0.0, 0.0)
# glEnable(GL_MULTISAMPLE)
# glEnable(GL_DEPTH_TEST)
# glEnable(GL_TEXTURE_2D)
self.init_shaders()
self.init_vbos()
def display(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBindVertexArray(self.obj_metadata["vao_id"])
glUseProgram(self.prog)
glUniform3f(glGetUniformLocation(self.prog, "color"), 0.0, 1.0, 0.0)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
glBindVertexArray(0)
glUseProgram(0)
glBindVertexArray(0)
glutSwapBuffers()
if __name__ == "__main__":
TestOpenglManager().run()
我一直在试图弄清楚上述片段可能出现的问题,而我不明白错误,应该画一个绿色的三角形而不是我&#39 ;得到一个黑屏
发生了什么?
答案 0 :(得分:1)
首先,您的vertex_stride
不正确。它应该是0
而不是3
。最后,在调用glDrawElements
时使用PyOpenGL,您需要传递None
或ctypes.c_void_p(0)
而不是0
。
事实是步幅是每个顶点属性之间的字节偏移。因此,您的顶点布局为:
X Y Z
X Y Z
X Y Z
然后在下一对0
之间存在X, Y, Z
个字节的偏移量。但是,如果您的顶点以这种方式布局:
X Y Z R G B
X Y Z R G B
X Y Z R G B
然后以3
(或更正确3 * sizeof(float)
)的步幅是正确的。