Python glBufferSubData,Haven';t实现了列表的类型推断,但没有实例呈现
移植第7章Superbible OpenGL第7版的实例渲染示例时遇到函数问题Python glBufferSubData,Haven';t实现了列表的类型推断,但没有实例呈现,python,python-3.x,opengl,glut,opengl-3,Python,Python 3.x,Opengl,Glut,Opengl 3,移植第7章Superbible OpenGL第7版的实例渲染示例时遇到函数问题glBufferSubData 无论我对它做什么,它都不会接受数据。将其转换为指针、字节字符串和列表本身。如果您有任何帮助,我们将不胜感激。多谢各位 更新:使用rabbi76的优秀答案,函数glBufferSubData现在正在接受数据,numpy版本非常好,ctypes版本是一个有见地的答案,非常好理解。另外,关于第二个参数,它确实需要是int或long,而不是python中的GLuint(0) 更新和成功:Rabb
glBufferSubData
无论我对它做什么,它都不会接受数据。将其转换为指针、字节字符串和列表本身。如果您有任何帮助,我们将不胜感激。多谢各位
更新:使用rabbi76的优秀答案,函数glBufferSubData
现在正在接受数据,numpy版本非常好,ctypes版本是一个有见地的答案,非常好理解。另外,关于第二个参数,它确实需要是int或long,而不是python中的GLuint(0)
更新和成功:Rabbid76的另一个非常好的答案是使渲染工作正常。
函数glvertexattributepointer
需要一个指向初始数据列表长度的指针,以便可以偏移。多谢各位
源代码:instancedattribs.py
#!/usr/bin/python3
import sys
import time
import ctypes
fullscreen = True
try:
from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, glBindVertexArray
except:
print ('''
ERROR: PyOpenGL not installed properly.
''')
sys.exit()
import numpy as np
square_buffer = GLuint(0)
square_vao = GLuint(0)
square_program = GLuint(0)
square_vs_source = '''
#version 410 core
layout (location = 0) in vec4 position;
layout (location = 1) in vec4 instance_color;
layout (location = 2) in vec4 instance_position;
out Fragment
{
vec4 color;
} fragment;
void main(void)
{
gl_Position = (position + instance_position) * vec4(0.25, 0.25, 1.0, 1.0);
fragment.color = instance_color;
}
'''
square_fs_source = '''
#version 410 core
precision highp float;
in Fragment
{
vec4 color;
} fragment;
out vec4 color;
void main(void)
{
color = fragment.color;
}
'''
class Scene:
def __init__(self, width, height):
global square_buffer
global square_vao
global square_program
self.width = width
self.height = height
square_vertices = np.array([
-1.0, -1.0, 0.0, 1.0,
1.0, -1.0, 0.0, 1.0,
1.0, 1.0, 0.0, 1.0,
-1.0, 1.0, 0.0, 1.0], dtype='float32')
instance_colors = np.array([
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
1.0, 1.0, 0.0, 1.0], dtype='float32')
instance_positions = np.array([
-2.0, -2.0, 0.0, 0.0,
2.0, -2.0, 0.0, 0.0,
2.0, 2.0, 0.0, 0.0,
-2.0, 2.0, 0.0, 0.0], dtype='float32')
glGenVertexArrays(1, square_vao)
glGenBuffers(1, square_buffer)
glBindVertexArray(square_vao)
glBindBuffer(GL_ARRAY_BUFFER, square_buffer)
offset = 0 # not GLuint(0)
bufferSize = (len(square_vertices) + len(instance_colors) + len(instance_positions))*4
glBufferData(GL_ARRAY_BUFFER, bufferSize, None, GL_STATIC_DRAW)
glBufferSubData(GL_ARRAY_BUFFER, offset, len(square_vertices)*4, square_vertices)
offset += len(square_vertices)*4
glBufferSubData(GL_ARRAY_BUFFER, offset, len(instance_colors)*4, instance_colors)
offset += len(instance_colors)*4
glBufferSubData(GL_ARRAY_BUFFER, offset, len(instance_positions)*4, instance_positions)
offset += len(instance_positions)*4
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, None)
offsetInstanceColor = len(square_vertices)*4
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(offsetInstanceColor))
offsetInstancPosition = (len(instance_colors) + len(instance_positions))*4
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(offsetInstancPosition))
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
glEnableVertexAttribArray(2)
glVertexAttribDivisor(1, 1)
glVertexAttribDivisor(2, 1)
square_program = glCreateProgram()
square_vs = GLuint(0)
square_vs = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(square_vs, square_vs_source)
glCompileShader(square_vs)
glAttachShader(square_program, square_vs)
square_fs = GLuint(0)
square_fs = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(square_fs, square_fs_source)
glCompileShader(square_fs)
glAttachShader(square_program, square_fs)
glLinkProgram(square_program)
glDeleteShader(square_vs)
glDeleteShader(square_fs)
def display(self):
black = [ 0.0, 0.0, 0.0, 0.0 ]
glClearBufferfv(GL_COLOR, 0, black)
glUseProgram(square_program)
glBindVertexArray(square_vao)
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, 4)
glutSwapBuffers()
def reshape(self, width, height):
self.width = width
self.height = height
def keyboard(self, key, x, y ):
global fullscreen
print ('key:' , key)
if key == b'\x1b': # ESC
sys.exit()
elif key == b'f' or key == b'F': #fullscreen toggle
if (fullscreen == True):
glutReshapeWindow(512, 512)
glutPositionWindow(int((1360/2)-(512/2)), int((768/2)-(512/2)))
fullscreen = False
else:
glutFullScreen()
fullscreen = True
print('done')
def init(self):
pass
def timer(self, blah):
glutPostRedisplay()
glutTimerFunc( int(1/60), self.timer, 0)
time.sleep(1/60.0)
if __name__ == '__main__':
start = time.time()
glutInit()
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(512, 512)
w1 = glutCreateWindow('OpenGL SuperBible - Instanced Attributes')
glutInitWindowPosition(int((1360/2)-(512/2)), int((768/2)-(512/2)))
fullscreen = False
many_cubes = False
#glutFullScreen()
scene = Scene(512,512)
glutReshapeFunc(scene.reshape)
glutDisplayFunc(scene.display)
glutKeyboardFunc(scene.keyboard)
glutIdleFunc(scene.display)
#glutTimerFunc( int(1/60), scene.timer, 0)
scene.init()
glutMainLoop()
预期渲染输出:
移植自:与,'s相比,大小
参数不能省略。您必须传递缓冲区的大小(以字节为单位)和指向缓冲区的指针。但是请注意,第二个和第三个参数必须是python
int
或long
,即使是PyOpneGL的GLuint
也会导致错误
您可以创建一个数组PyOpenGL的GLfloat
offset=0
数据数组=(GLfloat*len(正方形顶点))(*正方形顶点)
glBufferSubData(GL_数组_缓冲区,偏移量,len(数据数组)*4,数据数组)
或使用Python内置库:
导入ctypes
offset=0
dataArray=(ctypes.c_float*len(正方形顶点))(*正方形顶点)
glBufferSubData(GL_数组_缓冲区,偏移量,len(数据数组)*4,数据数组)
或创建一个数组:
将numpy导入为np
offset=0
dataArray=np.array(正方形顶点,dtype='float32')
glBufferSubData(GL_数组_缓冲区,偏移量,len(数据数组)*4,数据数组)
注意,对于第二个和三维参数,您可以使用强制转换为int
(例如int(offset)
)或long
(例如long(offset)
)
进一步注意,
glBufferData
、glBufferSubData
和glvertexattributepointer
的偏移量和大小参数是字节大小的值,而不是数组的元素数。字节大小由元素数乘以1个元素的大小计算得出。
1元素的大小是4,因为以字节为单位的
float
(GLfloat
,ctypes.c_float
,'float32'
)的大小是4
如果已绑定命名缓冲区对象,则glvertexattributepointer
的最后一个参数将被视为缓冲区对象数据存储区中的字节偏移量,但该参数的类型仍然是指针。
因此,您必须使用ctypes.c\u void\u p(偏移量)
。如果偏移量为0,则可以传递None
bufferSize=(len(正方形顶点)+len(实例颜色)+len(实例位置))*4
glBufferData(GL\ U数组\ U缓冲区、bufferSize、None、GL\ U静态\ U绘制)
glBufferSubData(GL_数组_缓冲区、偏移、len(方形顶点)*4、方形顶点)
偏移量+=透镜(正方形顶点)*4
glBufferSubData(GL_数组_缓冲区,偏移量,len(实例_颜色)*4,实例_颜色)
偏移量+=透镜(实例颜色)*4
glBufferSubData(GL_数组_缓冲区、偏移量、len(实例_位置)*4,实例_位置)
偏移量+=长度(实例位置)*4
glvertexattributepointer(0,4,GL\u浮点,GL\u假,0,无)
offsetInstanceColor=len(正方形顶点)*4
glvertexattributepointer(1,4,GL_FLOAT,GL_FALSE,0,ctypes.c_void_p(offsetInstanceColor))
offsetInstancPosition=(len(实例_颜色)+len(实例_位置))*4
glvertexattributepointer(2,4,GL_FLOAT,GL_FALSE,0,ctypes.c_void_p(offsetInstancePosition))
要创建gl上下文版本>2.1(您使用4.1)和
glut
请参见@Ripi2,我认为您将注释放在了错误的问题上。问题是如何使用PyOpenGL在python中将参数设置为glBufferSubData
。你的评论甚至与此无关。该示例运行良好,除了调用glBufferSubData
@Rabbid76之外,您可能是对的。但我们经常看到用户对他的问题给出错误的线索,不是吗?@Ripi2是的,你是对的,但在这种情况下不是。我已经接近答案了。请问*4是什么意思?它是否是numpy数组中每个数据元素的大小,因为它的类型是float32?@StanS。以字节为单位的大小是元素数乘以1个元素的大小。float
的大小为4字节。