Stanford Bunnyを読み込めたので,以下の2つに挑戦する.
- 自分で用意したシェーダを使う
- それをGLFWウィンドウに表示する
- やはりフレームは自分で更新したい
フォルダ構造
glfw_model_loading.py
resources
models/bunny/bunny.obj
などのファイルshaders
test_vs.glsl
: バーテクスシェーダtest_fs.glsl
: フラグメントシェーダ
コード
# glfw_model_loading.py from pathlib import Path import numpy as np import moderngl as mgl import moderngl_window as mglw from moderngl_window.conf import settings from moderngl_window import resources from moderngl_window.resources import programs, scenes from moderngl_window.meta import ProgramDescription, SceneDescription from moderngl_window.scene import Camera 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 = mglw.create_window_from_settings() # Resources self.resource_dir = Path(__file__).parent.resolve() / "resources" ## shaders resources.register_program_dir((self.resource_dir / "shaders").resolve()) self.program = programs.load( ProgramDescription( vertex_shader="test_vs.glsl", fragment_shader="test_fs.glsl", ) ) ## meshes resources.register_scene_dir((self.resource_dir / "models").resolve()) self.scene = scenes.load(SceneDescription(path="bunny/bunny.obj")) for mesh in self.scene.meshes: print(">> mesh.attributes:", mesh.attributes) print(">> len(self.scene.meshes):", len(self.scene.meshes)) # Camera self.camera = Camera(aspect_ratio=width / height, near=0.01, far=100.0) self.camera.set_position(0, 0.05, 0.5) self.camera.look_at(pos=(0, 0, 0)) def run(self) -> None: while not self.window.is_closing: self.window.ctx.enable_only(mgl.DEPTH_TEST) self.window.ctx.clear(1, 0, 0, 0) self.program["M"].write(np.identity(4, dtype="float32")) self.program["V"].write(self.camera.matrix) self.program["P"].write(self.camera.projection.matrix) self.scene.root_nodes[0].mesh.material.mat_texture.texture.use(0) self.scene.root_nodes[0].mesh.vao.render(self.program) self.window.swap_buffers() if __name__ == "__main__": app = App() app.run()
// test_vs.glsl #version 440 in vec3 in_position; in vec2 in_texcoord_0; in vec3 in_normal; uniform mat4 M; // model matrix uniform mat4 V; // view matrix uniform mat4 P; // projection matrix out vec3 vsNormal; out vec2 vsTexCoord; void main() { vsTexCoord = in_texcoord_0; vsNormal = in_normal; gl_Position = P * V * M * vec4(in_position, 1.0); }
// test_fs.glsl #version 440 layout (binding = 0) uniform sampler2D diffuseMap; layout (binding = 1) uniform sampler2D specularMap; layout (binding = 2) uniform sampler2D normalMap; layout (binding = 3) uniform sampler2D heightMap; in vec3 vsNormal; in vec2 vsTexCoord; out vec4 fsColor; void main() { fsColor = texture2D(diffuseMap, vsTexCoord); }
解説
glfw_model_loading.py
- line 16: ここでGLFWを指定
- lines 24 - 30: シェーダの読み込み
- lines 43 - 54: メインループ
- line 58: メインループを実行
test_vs.glsl
&test_fs.glsl
- シェーダはごく普通のテクスチャマッピングをするだけのもの.
結果
本当に簡単で直観的.ちなみに,バーテクスシェーダとフラグメントシェーダは合わせて一つのファイルに書き込める様子(参考:ModernGL-Window/examples).