3DCG

Python3で「OpenGL」を学ぶ 「ModernGL」Context を作成

イントロダクション

Context(コンテキスト)とは、かんたんに説明すると opengl の命令へのアクセスを可能にするオブジェクトのこと。Contextがどのように作成されるかは、ターゲットとなる、OSとプラットフォーム依存する。

ほとんどの場合、OSでサポートされているデフォルトのコンテキストバックエンドを使用する。このバックエンドは、特定のバックエンドパラメータを使用しない限り自動的に選択される。

OSごとのデフォルトバックエンドを以下の通り。

  • Windows: wgl / opengl32.dll
  • Linux: x11 / glx / libGL
  • OS X: CGL

これらのデフォルトのバックエンドは2つのモードをサポートしている。

  1. glfw, sdl2, pyglet などのウィンドウライブラリによって作成された可能性のあるアクティブなコンテキストの終了を検出する。
  2. ヘッドレスコンテキストの作成

ウィンドウライブラリによって作成された既存のアクティブコンテキストにアタッチする。

import moderngl
# .. do window initialization here
ctx = moderngl.create_context()
# If successful we can now render to the window
print("Default framebuffer is:", ctx.screen)

ヘッドレスコンテキストを作成する。

import moderngl
# Create the context
ctx = moderngl.create_context(standalone=True)
# Create a framebuffer we can render to
fbo = ctx.simple_framebuffer((100, 100), 4)
fbo.use()

必須環境:OpenGLバージョン

ModernGLは3.3+のコンテキストのみをサポートしている。デフォルトでは、バックエンドが返すコンテキストの最小必要バージョンとしてバージョン 3.3 が渡される。

特定のバージョンを要求する方法(OpenGL 4.3を要求、低いバージョンのコンテキストが返された場合、コンテキストの作成は失敗する)

moderngl.create_context(require=430)

この属性は Context.version_code でアクセスすることができ、コンテキストの実際のバージョンコードを含むように更新される(必要以上に高い場合)。

コンテキストバックエンドの指定

バックエンドを渡すことで、より高度な使い方ができる。例えば、以下のように、Linux上でヘッドレスEGLコンテキストを作成する。

ctx = moderngl.create_context(standalone=True, backend='egl')

コンテキストの共有

警告: 実験的な機能

いくつかのコンテキストは、コンテキスト間でのオブジェクト共有を可能にする共有パラメータをサポートしている。これは、共有モードを有効にして既存のコンテキストにアタッチする場合には必要ない。例えば、オブジェクトの共有を有効にした glfw で 2 つのウィンドウを作成する場合。

ModernGLオブジェクト(moderngl.Buffer、moderngl.Texture、…)は、作成されたコンテキストを含むctxプロパティを持っている。ModernGLは、これらのオブジェクトにアクセスする際に、現在どのコンテキストがアクティブであるかをチェックない。つまり、共有が有効になっている場合、オブジェクトは両方のコンテキストで使用できる。

理論的には、オブジェクトの共有が有効になっていれば問題なく動作するはずである。

data1 = numpy.array([1, 2, 3, 4], dtype='u1')
data2 = numpy.array([4, 3, 2, 1], dtype='u1')

ctx1 = moderngl.create_context(standalone=True)
ctx2 = moderngl.create_context(standalone=True, share=True)

with ctx1 as ctx:
    b1 = ctx.buffer(data1)

with ctx2 as ctx:
    b2 = ctx.buffer(data2)

print(b1.glo)  # Displays: 1
print(b2.glo)  # Displays: 2

with ctx1:
    print(b1.read())
    print(b2.read())

with ctx2:
    print(b1.read())
    print(b2.read())

オブジェクトの共有にはいくつかの制限がある。特に他のオブジェクトを参照するオブジェクト(フレームバッファ、頂点配列オブジェクトなど)

参考にした記事はこちら