Open16

WebGL-Native: WebGLの実装

prev: https://zenn.dev/okuoku/scraps/99fa92f6aae12e
next: https://zenn.dev/okuoku/scraps/7bf87a81129b7d

WebGLの実装

前回までで、Node.jsからOpenGL ES2を呼び出す環境を作ることができた。ということは、後はひたすらWebGLのメソッドを埋めていけばWebGL実装のできあがりということになる。(ステートの読み出しは対応してないけど)

... というわけで、全14章あるものを無心に実装していく。。

5.14.1 Attributes

drawingBufferWidth drawingBufferHeight は、とりあえず初期化時のサイズをそのまま返却することにした。

canvas は一旦ユーザ側で埋めてもらうって事で。。初期化APIを替えちゃった方が良いな ★ 。

5.14.5 Buffer objects

最初 lengthbyteLength をとり違えてた。。JavaScriptの length は要素数なので、 Uint32Array 等が来る可能性を考えると常に byteLength を使うのが正しい。

↓ のようなテストで、常に 32 バイトしかバッファされなくて発覚した。

    let buf = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 32, gl.STATIC_DRAW);
    console.log(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE)); // ★ → 32
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(32), gl.STATIC_DRAW);
    console.log(gl.getBufferParameter(gl.ELEMENT_ARRAY_BUFFER, gl.BUFFER_SIZE)); // ★ → 128
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    gl.deleteBuffer(buf); // ★ 本来不要

あと、WebGLの仕様では、 deleteBuffer は明示的にやらなくても良いので、GCとの統合を実装しておく必要がある。C言語側でやるか。JS側でやるか悩み中。

https://github.com/okuoku/cwgl-proto/issues/5

5.14.6 Framebuffer objects

void deleteFramebuffer(WebGLFramebuffer? buffer)

If framebuffer was generated by a different WebGLRenderingContext than this one,

仕様書のtypoかな(仮引数が bufferframebuffer)。

↓に書いた通り、UnityがWebGLの DEPTH_STENCIL renderbufferを活用しているため、暗黙にステンシルバッファを生成してバインドするコードを追加している。

5.14.7 Renderbuffer objects

これも DEPTH_STENCIL の専用対応。こういうのはJS側でやった方が良い気がしているが、そもそも何でWebGLとOpenGLで差があるのかを調べた方が良さそう ★ 。どうせDirectXの仕様じゃないかなという気はするけど。

5.14.10 Uniforms and attributes

最後の大物。。

EmscriptenはUniformのリストを事前に展開して整数idにマップするようになっているので、 getActiveUniform の実装が必須だった。というわけで追加している。

あと、仕様( https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glUniform.xml )の"number of elements"の意味をとり違えていて、要素数をそのまま渡していた。ベクタの長さで割るのが正解。

出画した

長く苦しい戦いだった。。

ログインするとコメントできます