【发布时间】:2022-10-01 15:05:46
【问题描述】:
我在尝试将参数传递给着色器时遇到了问题。
我的基类如下所示:
import pygame as pg
import sys
from core.input import Input
class Base(object):
def __init__(self, screen_size=[512, 512]):
pg.init()
display_flags = pg.DOUBLEBUF | pg.OPENGL
pg.display.gl_set_attribute(pg.GL_MULTISAMPLEBUFFERS, 1)
pg.display.gl_set_attribute(pg.GL_MULTISAMPLESAMPLES, 4)
pg.display.gl_set_attribute(
pg.GL_CONTEXT_PROFILE_MASK,
pg.GL_CONTEXT_PROFILE_CORE
)
self._Screen = pg.display.set_mode(screen_size, display_flags)
# set caption on window
pg.display.set_caption(\"Solar System Simulation\")
self._Running = True
self._Clock = pg.time.Clock()
# for user input
self._Input = Input()
def initilize(self) -> None:
pass
def update(self) -> None:
pass
def run(self) -> None:
# startup
self.initilize()
# main loop
while self._Running:
# handle input
self._Input.update()
if self._Input._Quit:
self._Running = False
# update
self.update()
# render
pg.display.flip()
# sync clock
self._Clock.tick(60)
# shutdown
pg.quit()
sys.exit()
使用它我可以成功运行以下测试代码:
from core.base import Base
from core.openGLUtils import OpenGLUtils
from OpenGL.GL import *
class Test(Base):
def initilize(self) -> None:
print(\"Init program...\")
# vertex shader
vert_code = \"\"\"
void main()
{
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
\"\"\"
# fragment shader
frag_code = \"\"\"
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
\"\"\"
# print OpenGL info
OpenGLUtils.printSystemInfo()
# send code to GPU - compile - store - reference
self.program_ref = OpenGLUtils.initializeProgram(vert_code, frag_code)
# set vert arrat obj
vao_ref = glGenVertexArrays(1)
glBindVertexArray(vao_ref)
# render settings (optional)
glPointSize(10)
def update(self) -> None:
# select program for rendering
glUseProgram(self.program_ref)
# render geometric objects using selected programs
glDrawArrays(GL_POINTS, 0, 1)
Test().run()
但是当我添加一个属性类时:
from OpenGL.GL import *
import numpy
class Attribute(object):
def __init__(self, data_type, data):
# type of element: int | float | vec2 | vec3 | vec4
self._DataType = data_type
# array of data to be stored in buffer
self._Data = data
# reference of available buffer from GPU
self._BufferRef = glGenBuffers(1)
# upload data immediately
self.uploadData()
def uploadData(self):
# convert data to numpy array format
# convert numbers to 32 bit floats
data = numpy.array(self._Data).astype(numpy.float32)
# select buffer used by the following functions
glBindBuffer(GL_ARRAY_BUFFER, self._BufferRef)
glBufferData(GL_ARRAY_BUFFER, data.ravel(), GL_STATIC_DRAW)
# associate variable in program with this bugger
def associateVariable(self, program_ref, variable_name):
# get reference for program variable with given name
variable_ref = glGetAttribLocation(program_ref, variable_name)
# if the program does not reference the variabel, then exit
if variable_ref == -1:
return
# select buffer used by the following functions
glBindBuffer(GL_ARRAY_BUFFER, self._BufferRef)
# specify how data will be read from the currently bound buffer into the specified variable
if self._DataType == \"int\":
glVertexAttribPointer(variable_ref, 1, GL_INT, GL_FALSE, 0, None)
elif self._DataType == \"float\":
glVertexAttribPointer(variable_ref, 1, GL_FLOAT, GL_FALSE, 0, None)
elif self._DataType == \"vec2\":
glVertexAttribPointer(variable_ref, 2, GL_FLOAT, GL_FALSE, 0, None)
elif self._DataType == \"vec3\":
glVertexAttribPointer(variable_ref, 3, GL_FLOAT, GL_FALSE, 0, None)
elif self._DataType == \"vec4\":
glVertexAttribPointer(variable_ref, 4, GL_FLOAT, GL_FALSE, 0, None)
else:
raise Exception(f\"Attribute {variable_name} has unknown type {self._DataType}\")
# indicate that data will be streamed to this variable
glEnableVertexAttribArray(variable_ref)
并运行以下测试代码:
from core.base import Base
from core.openGLUtils import OpenGLUtils
from core.attribute import Attribute
from OpenGL.GL import *
class Test(Base):
def initilize(self) -> None:
print(\"Initializing program...\")
# vert
vs_code = \"\"\"
in vec3 position;
void main()
{
gl_Position = vec4(
position.x, position.y, position.z, 1.0
);
}
\"\"\"
# frag
fs_code = \"\"\"
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
\"\"\"
self._ProgramRef = OpenGLUtils.initializeProgram(vs_code, fs_code)
# render settings (optional)
glLineWidth(4)
# set up vertex array object
vao_ref = glGenVertexArrays(1)
glBindVertexArray(vao_ref)
# set up vertex attribute
position_data = [
[0.8, 0.0, 0.0], [0.4, 0.6, 0.0],
[-0.4, 0.6, 0.0], [-0.8, 0.0, 0.0],
[-0.4, -0.6, 0.0], [0.4, -0.6, 0.0]
]
self._VertexCount = len(position_data)
positionAttribute = Attribute(\"vec3\", position_data)
positionAttribute.associateVariable(self._ProgramRef, \"position\")
return super().initilize()
def update(self) -> None:
glUseProgram(self._ProgramRef)
glDrawArrays(GL_LINE_LOOP, 0, self._VertexCount)
return super().update()
Test().run()
导致以下错误消息:
pygame 2.1.2 (SDL 2.0.16, Python 3.8.14)
Hello from the pygame community. https://www.pygame.org/contribute.html
Initializing program...
Unable to load numpy_formathandler accelerator from OpenGL_accelerate
Traceback (most recent call last):
File \"/home/jesper/dev/python3/solarpy/src/test2.py\", line 58, in <module>
Test().run()
File \"/home/jesper/dev/python3/solarpy/src/core/base.py\", line 38, in run
self.initilize()
File \"/home/jesper/dev/python3/solarpy/src/test2.py\", line 48, in initilize
positionAttribute.associateVariable(self._ProgramRef, \"position\")
File \"/home/jesper/dev/python3/solarpy/src/core/attribute.py\", line 48, in associateVariable
glVertexAttribPointer(variable_ref, 3, GL_FLOAT, GL_FALSE, 0, None)
File \"src/latebind.pyx\", line 51, in OpenGL_accelerate.latebind.Curry.__call__
File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/GL/VERSION/GL_2_0.py\", line 469, in glVertexAttribPointer
contextdata.setValue( key, array )
File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/contextdata.py\", line 58, in setValue
context = getContext( context )
File \"/home/jesper/dev/python3/solarpy/lib/python3.8/site-packages/OpenGL/contextdata.py\", line 40, in getContext
raise error.Error(
OpenGL.error.Error: Attempt to retrieve context when no valid context
我已经阅读了我在 StackOverflow 上找到的相关问题,但没有任何运气。我也尝试过使用不同的 python 版本(3.8、3.10)。
我在运行 Ubuntu 22.04.1 LTS(相对全新安装)的 Lenovo Thinkpad T460 上。
系统信息:
Vendor: Intel
Renderer: Mesa Intel(R) HD Graphics 520 (SKL GT2)
OpenGL version supported: 4.6 (Compatibility Profile) Mesa 22.0.5
GLSL version supported: 4.60
是什么导致了这个问题?据我了解,当使用pygame.OPENGL 标志集调用pygame.display.set_mode() 时,pygame 应该创建一个上下文,这是我在base.py 中完成的。
标签: python python-3.x opengl pygame pyopengl