Open5

C-WebGL: グローバルステートの実装

okuokuokuoku

前回 列挙したステートを1つ1つ実装していく。

たとえば、 LINE_WIDTH であれば、

  1. getParameter メソッドによる取得
  2. lineWidth メソッドによる設定
  3. 設定時に ALIASED_LINE_WIDTH_RANGE に収まっているかどうかのチェック

が必要になる。 ...はずなんだけど、 そもそもGLES2の仕様書にチェックしろと書いてない (記憶が正しければ LINE_WIDTH が唯一で、この点はGLES3で修正されている) という問題がある。

また EXTENSIONS のようにWebGLでは削除されているステートもあるため、それらもチェックしつつ実装を埋めていく必要がある。

okuokuokuoku

実装定数 その1 (表6.18)

最初は実装定数を用意していく。これらは定数で lineWidth のような設定APIを持たない。(特に言及は無いが)WebGLの場合はWebGLコンテキストを生成したタイミングで決定され、以降変更されないということになる。

この中だと要注意なのは COMPRESSED_TEXTURE_FORMATS だろう。

  • WebGL1はGLES2と異なり圧縮テクスチャを一切仕様化していない。というわけで規格上はゼロ長の配列になる。
  • ただし、事実上全ての実装は圧縮テクスチャを実装していて、その場合は実装している圧縮テクスチャを含めて返却する必要がある → C-WebGLとしては常にゼロとは仮定できない
  • WebGLでは、 NUM_COMPRESSED_TEXTURE_FORMATS は存在しない(配列を返却するため)。

最後の NUM_ 問題があるのはGLES2では他に(WebGL1では不要な)Shader binaryしか無いため、 COMPRESSED_TEXTURE_FORMATS だけ特別あつかいする方向にする。

okuokuokuoku

見落し防止のため数が多いのを先に処理する。

getParameter

https://github.com/okuoku/yuniframe/commit/e17ba626e06791c138879c0cc48f354035574632

https://github.com/okuoku/yuniframe/commit/958caa913aa07f6c33881ab5923bce745b2a1578

すごい量だ。。

GLESでは glGet〜 APIとなっているが、WebGLではJavaScriptの動的型を活かして getParameter に纏められている。C-WebGLではそれをC言語に落とすために型ごとに再度バラすというちょっと不毛なことになっている。

enabledisableisEnabled

https://github.com/okuoku/yuniframe/commit/75b01961876d8d57b64733dd3b794352fe91c48a

WebGLにもGLESにも isEnabled というコマンドが存在し、WebGLで言うところの getParameter のサブセットに相当する動作をする。 ...じゃぁ getParameter だけで良くない。。?

okuokuokuoku

とりあえずグローバルステートは実装し終えた。。

depthRange はWebGLでは制約される

前のVulkanの調査 ではMetalのdepthRangeに制約があるという話を書いたけど、何とWebGLも同様の制約を入れていた。まぁ入れても良いんだけどMetal機材って最初からOpenGLだと思うんだけど何故この制約が。。

The WebGL API does not support depth ranges with where the near plane is mapped to a value greater than that of the far plane. A call to depthRange will generate an INVALID_OPERATION error if zNear is greater than zFar .

OpenGLの getError はエラーが消えるまで呼びつづけないといけない

これ知らなかった。。

Thus, glGetError should always be called in a loop, until it returns GL_NO_ERROR , if all error flags are to be reset.