python - 类型错误:预期 c_float_Array_12_Array_3 实例,得到 glm.vec3,seg 错误
问题描述
如何解决我试图将值分配给由glMapBufferRange
这是一个有问题的函数分配的内存的错误,因为没有在 python 中进行强制转换。我正在尝试为该内存分配值,尽管我遇到了标题中所述的错误。我也尝试创建一个np.array
尺寸为大小的,material
但无济于事。也许只是没有正确地做到这一点。
更新和成功!在 Rabbid76 的惊人帮助下,修复首先分配并能够分配到glMapBufferRange
内存,然后到 sbmloader.py,程序成功呈现。谢谢你。
最终结果也在我的 github PythonOpenGLSuperBible7Glut上找到
支持文件:hdrbloom_support.zip
预期的输出呈现是实际结果呈现的内容:
源代码:
#!/usr/bin/python3
import sys
import time
import ctypes
fullscreen = True
sys.path.append("./shared")
from sbmloader import SBMObject # location of sbm file format loader
from ktxloader import KTXObject # location of ktx file format loader
from textoverlay import OVERLAY_
from shader import shader_load, link_from_shaders
from sbmath import m3dDegToRad, m3dRadToDeg, m3dTranslateMatrix44, m3dRotationMatrix44, \
m3dMultiply, m3dOrtho, m3dPerspective, rotation_matrix, translate, m3dScaleMatrix44, \
scale, m3dLookAt, normalize
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
from math import cos, sin
import glm
identityMatrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
myobject = SBMObject()
ktxobject = KTXObject()
overlay = OVERLAY_()
MAX_SCENE_WIDTH = 2048
MAX_SCENE_HEIGHT = 2048
SPHERE_COUNT = 32
tex_src = GLuint(0)
tex_lut = GLuint(0)
render_fbo = GLuint(0)
filter_fbo = [ GLuint(0) for _ in range(2) ]
tex_scene = GLuint(0)
tex_brightpass = GLuint(0)
tex_depth = GLuint(0)
tex_filter = [ GLuint(0) for _ in range(2) ]
program_render = GLuint(0)
program_filter = GLuint(0)
program_resolve = GLuint(0)
vao = GLuint(0)
exposure = 1.0
mode = 0
paused = False
bloom_factor = 1.0
show_bloom = True
show_scene = True
show_prefilter = False
bloom_thresh_min = 0.8
bloom_thresh_max = 1.2
class UNIFORMS_:
class scene:
bloom_thresh_min = 0.8
bloom_thresh_max = 1.2
class resolve:
exposure = 1.0
bloom_factor = 1.0
scene_factor = 0
uniforms = UNIFORMS_()
ubo_transform = GLuint(0)
ubo_material = GLuint(0)
def load_shaders():
global program_render
global program_filter
global program_resolve
global uniforms
shaders = [GLuint(0), GLuint(0)]
if (program_render):
glDeleteProgram(program_render)
shaders[0] = shader_load("hdrbloom-scene.vs.glsl", GL_VERTEX_SHADER)
shaders[1] = shader_load("hdrbloom-scene.fs.glsl", GL_FRAGMENT_SHADER)
program_render = link_from_shaders(shaders, 2, True)
uniforms.scene.bloom_thresh_min = glGetUniformLocation(program_render, "bloom_thresh_min")
uniforms.scene.bloom_thresh_max = glGetUniformLocation(program_render, "bloom_thresh_max")
if (program_filter):
glDeleteProgram(program_filter)
shaders[0] = shader_load("hdrbloom-filter.vs.glsl", GL_VERTEX_SHADER)
shaders[1] = shader_load("hdrbloom-filter.fs.glsl", GL_FRAGMENT_SHADER)
program_filter = link_from_shaders(shaders, 2, True)
if (program_resolve):
glDeleteProgram(program_resolve)
shaders[0] = shader_load("hdrbloom-resolve.vs.glsl", GL_VERTEX_SHADER)
shaders[1] = shader_load("hdrbloom-resolve.fs.glsl", GL_FRAGMENT_SHADER)
program_resolve = link_from_shaders(shaders, 2, True)
uniforms.resolve.exposure = glGetUniformLocation(program_resolve, "exposure")
uniforms.resolve.bloom_factor = glGetUniformLocation(program_resolve, "bloom_factor")
uniforms.resolve.scene_factor = glGetUniformLocation(program_resolve, "scene_factor")
class Scene:
def __init__(self, width, height):
global myobject
global vao
global render_fbo
global tex_scene
global tex_brightpass
global tex_depth
global filter_fbo
global tex_filter
global tex_lut
global ubo_transform
global ubo_material
self.width = width
self.height = height
buffers = [ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 ]
glGenVertexArrays(1, vao)
glBindVertexArray(vao)
load_shaders()
exposureLUT = [ 11.0, 6.0, 3.2, 2.8, 2.2, 1.90, 1.80, 1.80, 1.70, 1.70, 1.60, 1.60, 1.50, 1.50, 1.40, 1.40, 1.30, 1.20, 1.10, 1.00 ]
glGenFramebuffers(1, render_fbo)
glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)
tex_scene = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, tex_scene)
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_scene, 0)
tex_brightpass = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, tex_brightpass)
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, tex_brightpass, 0)
tex_depth = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, tex_depth)
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tex_depth, 0)
glDrawBuffers(2, buffers)
#glGenFramebuffers(2, filter_fbo[0])
filter_fbo = [ glGenFramebuffers(1) for _ in range(2)]
#glGenTextures(2, tex_filter[0])
tex_filter = [glGenTextures(1) for _ in range(2)]
for i in range(0,2):
glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[i])
glBindTexture(GL_TEXTURE_2D, tex_filter[i])
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH if i==0 else MAX_SCENE_HEIGHT, MAX_SCENE_HEIGHT if i==0 else MAX_SCENE_WIDTH)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_filter[i], 0)
glDrawBuffers(1, buffers)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
tex_lut = glGenTextures(1)
glBindTexture(GL_TEXTURE_1D, tex_lut)
glTexStorage1D(GL_TEXTURE_1D, 1, GL_R32F, 20)
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 20, GL_RED, GL_FLOAT, exposureLUT)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
myobject.load("torus.sbm")
glGenBuffers(1, ubo_transform)
glBindBuffer(GL_UNIFORM_BUFFER, ubo_transform)
glBufferData(GL_UNIFORM_BUFFER, (2 + SPHERE_COUNT) * glm.sizeof(glm.mat4), None, GL_DYNAMIC_DRAW)
class material:
diffuse_color = glm.vec3
specular_color = glm.vec3
specular_power = GLfloat(0)
ambient_color = glm.vec3
glGenBuffers(1, ubo_material)
glBindBuffer(GL_UNIFORM_BUFFER, ubo_material)
size_material = ctypes.sizeof(ctypes.c_float) * 12;
glBufferData(GL_UNIFORM_BUFFER, SPHERE_COUNT * size_material, None, GL_STATIC_DRAW)
mat = glMapBufferRange(GL_UNIFORM_BUFFER, 0, SPHERE_COUNT * size_material, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
m = (GLfloat * 12 * SPHERE_COUNT).from_address(mat)
ambient = 0.002
for i in range(SPHERE_COUNT):
fi = 3.14159267 * i / 8.0
m[i][0:3] = (ctypes.c_float * 3)(sin(fi) * 0.5 + 0.5, sin(fi + 1.345) * 0.5 + 0.5, sin(fi + 2.567) * 0.5 + 0.5)
m[i][4:7] = (ctypes.c_float * 3)(2.8, 2.8, 2.9)
m[i][7] = 30
m[i][8:11] = (ctypes.c_float * 3)(ambient * 0.025, ambient * 0.025, ambient * 0.025)
ambient *= 1.5
glUnmapBuffer(GL_UNIFORM_BUFFER)
def display(self):
global program_filter
global program_resolve
global program_render
global tex_filter
global exposure
global vao
global filter_fbo
global ubo_transform
global ubo_material
global bloom_thresh_min
global bloom_thresh_max
global uniforms
global tex_brightpass
global myobject
global render_fbo
currentTime = time.time()
black = [ 0.0, 0.0, 0.0, 1.0 ]
one = 1.0
last_time = 0.0
total_time = 0.0
if (not paused):
total_time += (currentTime - last_time)
last_time = currentTime
t = total_time
glViewport(0, 0, self.width, self.height)
glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)
glClearBufferfv(GL_COLOR, 0, black)
glClearBufferfv(GL_COLOR, 1, black)
glClearBufferfv(GL_DEPTH, 0, one)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glUseProgram(program_render)
glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo_transform)
class transforms_t:
mat_proj = glm.mat4
mat_view = glm.mat4
mat_model = [glm.mat4 for _ in range(SPHERE_COUNT)]
size_transforms_t = glm.sizeof(glm.mat4) * (SPHERE_COUNT+2)
mbuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, size_transforms_t, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
bufferp = (GLfloat * 16 * (SPHERE_COUNT+2)).from_address(mbuffer)
mat_proj = (GLfloat * 16)(*identityMatrix)
mat_proj = m3dPerspective(m3dDegToRad(50.0), float(self.width) / float(self.height), 1.0, 1000.0)
T = (GLfloat * 16)(*identityMatrix)
m3dTranslateMatrix44(T, 0.0, 0.0, -20.0)
bufferp[0] = mat_proj
bufferp[1] = T
for i in range(2, SPHERE_COUNT+2):
fi = 3.141592 * i / 16.0
# // float r = cosf(fi * 0.25f) * 0.4f + 1.0f
r = 0.6 if (i & 2) else 1.5
T1 = (GLfloat * 16)(*identityMatrix)
m3dTranslateMatrix44(T1, cos(t + fi) * 5.0 * r, sin(t + fi * 4.0) * 4.0, sin(t + fi) * 5.0 * r)
RY = (GLfloat * 16)(*identityMatrix)
m3dRotationMatrix44(RY, currentTime * m3dDegToRad(30.0) * fi, sin(t + fi * 2.13) * 75.0, cos(t + fi * 1.37) * 92.0, 0.0)
m_model = (GLfloat * 16)(*identityMatrix)
m_model = m3dMultiply(T1, RY)
bufferp[i] = m_model
glUnmapBuffer(GL_UNIFORM_BUFFER)
glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo_material)
glUniform1f(uniforms.scene.bloom_thresh_min, bloom_thresh_min)
glUniform1f(uniforms.scene.bloom_thresh_max, bloom_thresh_max)
myobject.render(SPHERE_COUNT)
glDisable(GL_DEPTH_TEST)
glUseProgram(program_filter)
glBindVertexArray(vao)
glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[0])
glBindTexture(GL_TEXTURE_2D, tex_brightpass)
glViewport(0, 0, self.height, self.width)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[1])
glBindTexture(GL_TEXTURE_2D, tex_filter[0])
glViewport(0, 0, self.width, self.height)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
glUseProgram(program_resolve)
glUniform1f(uniforms.resolve.exposure, exposure)
if (show_prefilter):
glUniform1f(uniforms.resolve.bloom_factor, 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0)
else:
glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom else 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene else 0.0 )
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glActiveTexture(GL_TEXTURE1)
glBindTexture(GL_TEXTURE_2D, tex_filter[1])
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter else tex_scene)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 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
def init(self):
pass
def timer(self, blah):
glutPostRedisplay()
glutTimerFunc( int(1/60), self.timer, 0)
time.sleep(1/60.0)
if __name__ == '__main__':
glutInit()
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(512, 512)
w1 = glutCreateWindow('OpenGL SuperBible - HDR Bloom')
glutInitWindowPosition(int((1360/2)-(512/2)), int((768/2)-(512/2)))
fullscreen = 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()
移植自:hdrbloom.cpp Superbible Opengl 示例第 7 版。第 490 页
解决方案
首先注意,std140
uniform块中( )结构的内存布局
struct material_t { vec3 diffuse_color; vec3 specular_color; float specular_power; vec3 ambient_color; };
是
diffuse_color : 3 floats (x, y, z), 1 float alignment
specular_color : 3 floats (x, y, z),
specular_power : 1 float,
ambient_color : 3 floats (x, y, z), 1 float alignment
请阅读我是否应该使用vec3
统一缓冲区或着色器存储缓冲区对象的内部?
并查看OpenGL 4.6 API Core Profile Specification;7.6.2.2 标准统一块布局,第 144 页。
因此缓冲区的大小是12 * ctypes.sizeof(ctypes.c_float)
size_material = ctypes.sizeof(ctypes.c_float) * 12;
为统一块数组创建缓冲区:
layout (binding = 1, std140) uniform MATERIAL_BLOCK { material_t material[32]; } materials;
glBufferData(GL_UNIFORM_BUFFER, SPHERE_COUNT * size_material, None, GL_STATIC_DRAW)
将形状为( SPHERE_COUNT
, 12)的二维数组映射到缓冲存储器:
mat = glMapBufferRange(GL_UNIFORM_BUFFER, 0, SPHERE_COUNT * size_material, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
m = (GLfloat * 12 * SPHERE_COUNT).from_address(mat)
通过数组赋值在循环中赋值:
ambient = 0.002
for i in range(SPHERE_COUNT):
fi = 3.14159267 * i / 8.0
m[i][0:3] = (ctypes.c_float * 3)(sin(fi) * 0.5 + 0.5, sin(fi + 1.345) * 0.5 + 0.5, sin(fi + 2.567) * 0.5 + 0.5)
m[i][4:7] = (ctypes.c_float * 3)(2.8, 2.8, 2.9)
m[i][7] = 30
m[i][8:11] = (ctypes.c_float * 3)(ambient * 0.025, ambient * 0.025, ambient * 0.025)
ambient *= 1.5
第二个统一块的大小
layout (binding = 0, std140) uniform TRANSFORM_BLOCK { mat4 mat_proj; mat4 mat_view; mat4 mat_model[32]; } transforms;
是
size_transforms_t = glm.sizeof(glm.mat4) * (SPHERE_COUNT+2)
将形状为( (SPHERE_COUNT+2)
, 16)的二维数组映射到缓冲存储器:
mbuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, size_transforms_t, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
bufferp = (GLfloat * 16 * (SPHERE_COUNT+2)).from_address(mbuffer)
SBMObject.render_sub_object
不渲染实例。它必须是这样的:
def render_sub_object(self, object_index, instance_count, base_instance):
global index_type
glBindVertexArray(self.vao)
if instance_count == 0:
glDrawArrays(GL_TRIANGLES, 0, self.vertexcount)
else:
glDrawArraysInstancedBaseInstance(GL_TRIANGLES,
0,
self.vertexcount,
instance_count,
base_instance)
# [...]
show_prefilter
,show_bloom
并且show_scene
是布尔值,它们永远不会等于 0.0。均匀float bloom_factor
或float scene_factor
必须大于 0.0,否则片段颜色为黑色。
glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom==0 else 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene==0 else 0.0)
glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom else 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene else 0.0 )
glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter==0 else tex_scene)
glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter else tex_scene)
推荐阅读
- java - 在 Amazon SQS 队列中,我们对不同组 ID 的数量有限制吗?
- laravel-8 - 使用 Laravel 8 jetstream 的下拉框
- python - 如何对测试功能的每个参数执行 pytest 夹具?
- javascript - 如何使用 fect API 上传一组法师
- python - 在 python 中舍入随机数的最快方法
- php - 如何使用 laravel livewire 对 http 响应的结果进行分页
- flutter - 颤动,每当我进入 videoPlayerScreen 时,我的应用程序就会死机
- c++ - 类构造函数被误解
- javascript - 我可以使用 Mobx 商店制作可观察变量吗?
- angular - 使用 Karma Jasmine 在 Angular 的单元测试中无法读取未定义的属性“on”