前回は,既存のモデルデータを読み込んでいた.今度は自分で矩形のメッシュ (Quad) を定義して表示する.今回,少し問題に直面した...
フォルダ構造
glfw_quad.py
resources
shaders
uv_vs.glsl
: バーテクスシェーダuv_fs.glsl
: フラグメントシェーダ
コード
# glfw_quad.py from pathlib import Path import moderngl as mgl import moderngl_window from moderngl_window.conf import settings from moderngl_window import resources from moderngl_window.resources import programs from moderngl_window.meta import ProgramDescription from moderngl_window.scene.camera import Camera import numpy as np class Quad: def __init__(self, ctx: mgl.Context, prog: mgl.Program) -> None: self.prog = prog # Quad vertices = np.array([ # x, y, u, v -0.5, -0.5, 0.0, 0.0, # 0: Bottom left +0.5, -0.5, 1.0, 0.0, # 1: Bottom right +0.5, +0.5, 1.0, 1.0, # 2: Top right -0.5, +0.5, 0.0, 1.0, # 3: Top left ], dtype="f4") indices = np.array([0, 1, 2, 3], dtype="i4") self.vbo = ctx.buffer(vertices) self.ibo = ctx.buffer(indices) vao_content = [(self.vbo, "2f 2f", "in_vert", "in_uv")] self.vao = ctx.vertex_array(self.prog, vao_content, self.ibo) def render(self, camera: Camera) -> None: self.prog["M"].write(np.identity(4, dtype="f4")) self.prog["V"].write(camera.matrix) self.prog["P"].write(camera.projection.matrix) self.vao.render(mgl.TRIANGLE_FAN) class App: def __init__(self, width=512, height=512) -> None: # Window # create a gl window: https://moderngl-window.readthedocs.io/en/latest/reference/settings.conf.settings.html#moderngl_window.conf.Settings.WINDOW settings.WINDOW["class"] = "moderngl_window.context.glfw.Window" settings.WINDOW["gl_version"] = (4, 1) settings.WINDOW["size"] = (width, height) settings.WINDOW["aspect_ratio"] = width / height self.window = moderngl_window.create_window_from_settings() # Resources self.resource_dir = Path(__file__).parent.resolve() / "resources" resources.register_program_dir((self.resource_dir / "shaders").resolve()) self.program = programs.load( ProgramDescription(vertex_shader="uv_vs.glsl", fragment_shader="uv_fs.glsl") ) # Camera self.camera = Camera(aspect_ratio=width / height, near=0.01, far=100.0) self.camera.set_position(0, 0.0, 1.5) self.camera.look_at(pos=(0, 0, 0)) # Quad self.quad = Quad(self.window.ctx, self.program) def run(self) -> None: while not self.window.is_closing: self.window.clear(0.5, 1.0, 0.25, 0.0) self.window.ctx.enable(mgl.DEPTH_TEST | mgl.CULL_FACE) self.quad.render(self.camera) self.window.swap_buffers() if __name__ == "__main__": app = App() app.run()
// uv_vs.glsl #version 330 uniform mat4 M; // model matrix uniform mat4 V; // view matrix uniform mat4 P; // projection matrix in vec2 in_vert; in vec2 in_uv; out vec2 vs_uv; void main() { vs_uv = in_uv; gl_Position = P * V * M * vec4(in_vert, 0.0, 1.0); }
// uv_fs.glsl #version 330 in vec2 vs_uv; out vec4 fs_color; void main() { fs_color = vec4(vs_uv, 1.0, 1.0); }
解説
glfw_quad.py
- lines 13 - 37:
Quad
クラス- lines 18 - 24: 矩形の頂点を定義(z座標は直接シェーダから)
- line 25: 頂点の描画順を定義
- line 30: ここで引っかかった...(後述)
- lines 13 - 37:
uv_vs.glsl
&uv_fs.glsl
- uv座標を色として割り当てするシェーダ
結果
引っかかった問題
glfw_quad.py
のline 30でAttributeを指定しているが,指定されたAttributeがmain()
関数内で漏れなく使われていない場合,エラーでプログラムが落ちる様子.
例えば,uv_vs.glsl
の14行目をvs_uv = vec3(1.0, 1.0);
にするとエラーが発生.その時のエラーメッセージが以下のようなものなのだが,正直これでは何も分からん...
res.mglo, res._glo = self.mglo.vertex_array(program.mglo, content, index_buffer_mglo, moderngl.error.Error: content[0][3] must be an attribute not NoneType
この辺りの問題は,v5.7で軽減する方法がリリースされる?(参考:https://github.com/moderngl/moderngl/issues/459).