PyOpenGL
PyOpenGL is the most common cross platform Python binding to OpenGL and related APIs. The binding is created using the standard ctypes library, and is provided under an extremely liberal BSD-style Open-Source license.
Categories
PyOpenGL_accelerate
INFORMATION |
참고로 PyOpenGL_accelerate는 PyOpenGL과 완벽하게 호환되며, 기존 PyOpenGL 코드를 수정하지 않고도 성능 개선 효과를 누릴 수 있습니다. |
PyOpenGL_accelerate 는 USE_ACCELERATE
환경변수로 ON/OFF 제어할 수 있다.
다음은 OpenGL/acceleratesupport.py
파일 내용이다:
"""Common code for accelerated modules"""
import logging
from OpenGL import _configflags
needed_version = (3, 1, 6)
_log = logging.getLogger("OpenGL.acceleratesupport")
try:
import OpenGL_accelerate
if _configflags.USE_ACCELERATE:
if OpenGL_accelerate.__version_tuple__ < needed_version:
_log.warning(
"""Incompatible version of OpenGL_accelerate found, need at least %s found %s""",
needed_version,
OpenGL_accelerate.__version_tuple__,
)
raise ImportError("""Old version of OpenGL_accelerate""")
ACCELERATE_AVAILABLE = True
_log.debug("""OpenGL_accelerate module loaded""")
else:
raise ImportError("""Acceleration disabled""")
except ImportError as err:
_log.info("""No OpenGL_accelerate module loaded: %s""", err)
ACCELERATE_AVAILABLE = False
_configflags.USE_ACCELERATE
는 USE_ACCELERATE
환경변수를 가져오는 코드이다.
Environment Variables
-
PYOPENGL_ERROR_CHECKING = True
-
PYOPENGL_ERROR_LOGGING = False
-
PYOPENGL_ERROR_ON_COPY = False
-
PYOPENGL_ARRAY_SIZE_CHECKING = True
-
PYOPENGL_STORE_POINTERS = True
-
PYOPENGL_USE_ACCELERATE = True
- PyOpenGL_accelerate 사용 여부 -
PYOPENGL_CONTEXT_CHECKING = False
-
PYOPENGL_FULL_LOGGING = False
-
PYOPENGL_ALLOW_NUMPY_SCALARS = False
-
PYOPENGL_UNSIGNED_BYTE_IMAGES_AS_STRING = True
-
PYOPENGL_UNSIGNED_BYTE_IMAGES_AS_STRING = True
-
PYOPENGL_PLATFORM = '...'
- 플랫폼 지정
Platforms
PlatformPlugin("nt", "OpenGL.platform.win32.Win32Platform")
PlatformPlugin("darwin", "OpenGL.platform.darwin.DarwinPlatform")
PlatformPlugin("linux2", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("linux", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("glx", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("posix", "OpenGL.platform.glx.GLXPlatform")
PlatformPlugin("x11", "OpenGL.platform.glx.GLXPlatform") # xdg session type
PlatformPlugin("osmesa", "OpenGL.platform.osmesa.OSMesaPlatform")
PlatformPlugin("egl", "OpenGL.platform.egl.EGLPlatform")
PlatformPlugin("wayland", "OpenGL.platform.egl.EGLPlatform") # xdg session type
PlatformPlugin(
"xwayland", "OpenGL.platform.egl.EGLPlatform"
) # xdg session type, but use egl even though normally you'd expect GLX
OpenGL.setPlatform('egl')
같은 식으로 호출하거나 PYOPENGL_PLATFORM
환경변수를 설정해도 된다.
Example
PyOpenGL_accelerate
는 하드웨어 가속인듯.
샘플 코드:
import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy
def main():
# initialize glfw
if not glfw.init():
return
window = glfw.create_window(800, 600, "My OpenGL window", None, None)
if not window:
glfw.terminate()
return
glfw.make_context_current(window)
# positions colors
triangle = [-0.5, -0.5, 0.0, 1.0, 0.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0, 0.0,
0.0, 0.5, 0.0, 0.0, 0.0, 1.0]
triangle = numpy.array(triangle, dtype = numpy.float32)
vertex_shader = """
#version 330
in vec3 position;
in vec3 color;
out vec3 newColor;
void main()
{
gl_Position = vec4(position, 1.0f);
newColor = color;
}
"""
fragment_shader = """
#version 330
in vec3 newColor;
out vec4 outColor;
void main()
{
outColor = vec4(newColor, 1.0f);
}
"""
shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
OpenGL.GL.shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, 72, triangle, GL_STATIC_DRAW)
position = glGetAttribLocation(shader, "position")
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(0))
glEnableVertexAttribArray(position)
color = glGetAttribLocation(shader, "color")
glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 24, ctypes.c_void_p(12))
glEnableVertexAttribArray(color)
glUseProgram(shader)
glClearColor(0.2, 0.3, 0.2, 1.0)
while not glfw.window_should_close(window):
glfw.poll_events()
glClear(GL_COLOR_BUFFER_BIT)
glDrawArrays(GL_TRIANGLES, 0, 3)
glfw.swap_buffers(window)
glfw.terminate()
if __name__ == "__main__":
main()
큐브를 돌리는 예제
OpenGL with PyOpenGL introduction and creation of Rotating Cube
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
verticies = (
(1, -1, -1),
(1, 1, -1),
(-1, 1, -1),
(-1, -1, -1),
(1, -1, 1),
(1, 1, 1),
(-1, -1, 1),
(-1, 1, 1)
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7)
)
def Cube():
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glTranslatef(0.0,0.0, -5)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(1, 3, 1, 1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
Cube()
pygame.display.flip()
pygame.time.wait(10)
main()
Drawing Object
Troubleshooting
__________________ ERROR collecting tester/test_entrypoint.py __________________
tester/test_entrypoint.py:8: in <module>
from ddrm.entrypoint import main as entrypoint_main
ddrm/entrypoint.py:8: in <module>
from ddrm.apps import run_app
ddrm/apps/__init__.py:21: in <module>
from ddrm.apps.player import Player
ddrm/apps/player/__init__.py:10: in <module>
from OpenGL import GL
/usr/local/lib/python3.11/site-packages/OpenGL/GL/__init__.py:4: in <module>
from OpenGL.GL.VERSION.GL_1_1 import *
/usr/local/lib/python3.11/site-packages/OpenGL/GL/VERSION/GL_1_1.py:14: in <module>
from OpenGL.raw.GL.VERSION.GL_1_1 import *
/usr/local/lib/python3.11/site-packages/OpenGL/raw/GL/VERSION/GL_1_1.py:7: in <module>
from OpenGL.raw.GL import _errors
/usr/local/lib/python3.11/site-packages/OpenGL/raw/GL/_errors.py:4: in <module>
_error_checker = _ErrorChecker( _p, _p.GL.glGetError )
E AttributeError: 'NoneType' object has no attribute 'glGetError'
libgl1-mesa-dev
를 설치하면 된다:
OpenGL.error.Error: Attempt to retrieve context when no valid context
Ubuntu 20.04 이상에서 Wayland 로 실행된다면 다음과 같은 에러가 출력될 수 있다:
pygame-ce 2.4.1 (SDL 2.28.5, Python 3.11.4)
/home/your/Project/ddrm/test.py:13: Warning: PyGame seems to be running through X11 on top of wayland, instead of wayland directly
...
OpenGL.error.Error: Attempt to retrieve context when no valid context
다음과 같이 SDL_VIDEO_X11_FORCE_EGL=1
환경변수 설정하면 된다:
numpy.dtype size changed, may indicate binary incompatibility
('numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject', 1, <OpenGL.platform.baseplatform.glGenTextures object at 0x72b5e17db840>)
Traceback (most recent call last):
File "/home/your/Project/ddrm/ddrm/apps/__init__.py", line 96, in run_app
app.start()
File "/home/your/Project/ddrm/ddrm/apps/player/__init__.py", line 52, in start
self.on_init()
File "/home/your/Project/ddrm/ddrm/apps/player/__init__.py", line 73, in on_init
self._renderer = PygameRenderer()
^^^^^^^^^^^^^^^^
File "/home/your/Project/ddrm/ddrm/apps/player/renderer.py", line 18, in __init__
super().__init__()
File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/imgui/integrations/base.py", line 18, in __init__
self.refresh_font_texture()
File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/imgui/integrations/opengl.py", line 247, in refresh_font_texture
self._font_texture = gl.glGenTextures(1)
^^^^^^^^^^^^^^^^^^^
File "src/latebind.pyx", line 39, in OpenGL_accelerate.latebind.LateBind.__call__
File "src/wrapper.pyx", line 303, in OpenGL_accelerate.wrapper.Wrapper.__call__
File "src/wrapper.pyx", line 88, in OpenGL_accelerate.wrapper.CArgCalculator.c_call
File "src/wrapper.pyx", line 69, in OpenGL_accelerate.wrapper.CArgCalculatorElement.c_call
File "src/wrapper.pyx", line 64, in OpenGL_accelerate.wrapper.CArgCalculatorElement.c_call
File "src/arraydatatype.pyx", line 355, in OpenGL_accelerate.arraydatatype.SizedOutputOrInput.c_call
File "src/arraydatatype.pyx", line 224, in OpenGL_accelerate.arraydatatype.ArrayDatatype.c_zeros
File "src/arraydatatype.pyx", line 69, in OpenGL_accelerate.arraydatatype.HandlerRegistry.c_get_output_handler
File "src/arraydatatype.pyx", line 80, in OpenGL_accelerate.arraydatatype.HandlerRegistry.c_handler_by_plugin_name
File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/plugins.py", line 18, in load
return importByName( self.import_path )
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/plugins.py", line 45, in importByName
module = __import__( ".".join(moduleName), {}, {}, moduleName)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/your/Project/ddrm/.venv/lib/python3.11/site-packages/OpenGL/arrays/numpymodule.py", line 28, in <module>
from OpenGL_accelerate.numpy_formathandler import NumpyHandler
File "src/numpy_formathandler.pyx", line 1, in init OpenGL_accelerate.numpy_formathandler
ValueError: ('numpy.dtype size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject', 1, <OpenGL.platform.baseplatform.glGenTextures object at 0x72b5e17db840>)
그냥 PyOpenGL_accelerate
를 지우자.