gpt4 book ai didi

python - glBufferSubData ,尚未实现列表的类型推断 - 实例化渲染

转载 作者:行者123 更新时间:2023-12-01 07:39:14 27 4
gpt4 key购买 nike

移植来自 Superbible OpenGL 7th ed 的第 7 章实例渲染示例。并遇到函数 glBufferSubData

的问题

无论我对它做什么,它都不会接受数据。把它变成一个指针,一个字节串,列表本身。请帮助我们,我们将不胜感激。谢谢。

更新:使用 Rabbid76 的出色答案,函数 glBufferSubData 现在正在接受数据,并且 numpy 版本非常好,ctypes 版本是一个富有洞察力的答案,非常很高兴知道。另外,关于第二个参数,它确实需要是 int 或 long,而不是 python 中的 GLuint(0)

更新和成功:Rabbid76 的另一个非常好的答案,使渲染工作正常。函数glVertexAttribPointer需要一个指向初始数据列表长度的指针,以便它可以偏移。非常感谢。

源代码: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()

预期渲染输出: picture of output of rendering

移植自:instancedattribs.cpp

最佳答案

glBufferData 相比, PyOpenGlglBufferSubData size 参数不能省略。
您必须传递缓冲区的大小(以字节为单位)和指向缓冲区的指针。但请注意,第二个和第三个参数必须是 python intlong,即使是 PyOpneGL 的 GLuint 也会导致错误。

你有一些可能性,要么创建一个 PyOpenGL 的 GLfloat 数组

offset = 0
dataArray = (GLfloat*len(square_vertices))(*square_vertices)
glBufferSubData(GL_ARRAY_BUFFER, offset, len(dataArray)*4, dataArray)

或者使用内置的python ctypes图书馆:

import ctypes
offset = 0
dataArray = (ctypes.c_float*len(square_vertices))(*square_vertices)
glBufferSubData(GL_ARRAY_BUFFER, offset, len(dataArray)*4, dataArray)

或创建一个NumPy数组:

import numpy as np 
offset = 0
dataArray = np.array(square_vertices, dtype='float32')
glBufferSubData(GL_ARRAY_BUFFER, offset, len(dataArray)*4, dataArray)

请注意,对于第二个和第三个参数,您可以使用强制转换为 int (例如 int(offset))或 long (例如long(offset))。

<小时/>

进一步注意,glBufferDataglBufferSubDataglVertexAttribPointer 的偏移量和大小参数是字节大小的值,而不是元素的数量数组。
大小(以字节为单位)的计算方法是元素数量乘以 1 个元素的大小。
1 个元素的大小为 4,因为 float 的大小 (GLfloat, ctypes.c_float, 'float32') 以字节为单位是 4。

如果绑定(bind)了命名缓冲区对象,则 glVertexAttribPointer 的最后一个参数将被视为缓冲区对象数据存储中的字节偏移量,但参数的类型仍然是指针。所以你必须使用ctypes.c_void_p(offset)。如果偏移量为 0,则可以传递 None

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))
<小时/>

关于python - glBufferSubData ,尚未实现列表的类型推断 - 实例化渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56810151/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com