Go で作ったゲームを Android/iOS 対応させた話 (4)

[Go で作ったゲームを Android/iOS 対応させた話 (3)](http://qiita.com/hajimehoshi/items/4eb6143ea25f9e5cda33) の続き。前の投稿から随分時間が空いてしまいました。今回から iOS 版の実装が始まります。 OpenGL の罠に次々とハマっていく様子が分かります。

# 日記

## 2016-06-07

### 黒い点滅の修正 ([1](https://github.com/hajimehoshi/ebiten/commit/83a96dc532adfde2e675b0bd3ecee927c2a822d5), [2](https://github.com/hajimehoshi/ebiten/commit/cabea248156111011603231e1b8e269da7611519))

「なぜか `glFlush` を呼ぶと直る」シリーズの一つ。コマンド実行後に明示的に `glFlush` を呼ばないと、 Android 上で黒い点滅が出てしまうので、呼ぶように修正。前回 `glFlush` をパフォーマンス向上のために削減したが、それの反動のような修正である。

## 2016-06-10

特筆することは特になく、リファクタリング的なことが多い。というか自分も何をやったのかだいぶ忘れている…。

## 2016-06-12

### [delayedImageTasks の撤廃](https://github.com/hajimehoshi/ebiten/commit/fabed66b4a9b1c2da01cfb1c2e3c33b41c553a41)

いままで delayedImageTasks という main が実行されるまでの描画コマンドタスクラインと、それとは別にアプリケーション実行中の描画コマンドタスクラインの 2 つが併存していた。 init 中に発行される描画コマンドは前者にためられる。 2 つは本質的に同じものなので、後者に統一した。

## 2016-06-14

### [画面ちらつきの修正](https://github.com/hajimehoshi/ebiten/commit/6640f60c8829670c94583b84e65ea664c9d5b8b4)

これは Ebiten のロジックバグのようなそうでないような何かだが、「何フレーム分更新した後に描画するか」の計算の際、 0 だった場合に何もしていなかったのが良くなかった。描画済みのフレームを再描画してあげることで修正。

## 2016-06-15

### [iOS 向け開発開始](https://github.com/hajimehoshi/ebiten/commit/13f594baed10bd35b7bd353dacd739e79aefad90)

Android 版がひとまず落ち着いたので、 iOS 版に向けた開発を開始した。

## 2016-06-17

### [ビルドタグ `ios` を使用](https://github.com/hajimehoshi/ebiten/commit/dfe4db67bea5e8190f0e125264b0d57f9ce66caf)

`ios` というビルドタグが使えるので利用する。なお iOS は基本的に `darwin,arm` か  `darwin,arm64` だが、エミュレータも入れると `darwin,amd64` もある。

### [`glGetShaderPrecisionFormat` を使った highp 使用判定](https://github.com/hajimehoshi/ebiten/commit/0b8fe2535084918d4338c022f90fd9f38be3e252)

`glGetShaderPrecisionFormat` を使って highp の有無を調べるというもの。 OpenGL ES または WebGL のときに highp などを使い、そうでない OpenGL の場合は使わない (というか使えない) というのを判別する意図なのだが、この用途で `glGetShaderPrecisionFormat` を使うのは良くなかった。単に [GLSL 内で `#ifdef GL_ES` を使えばいい](https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_03)ことが随分後に判明する。

## 2016-06-18

### [iOS の描画先フレームバッファが 0 ではない問題の修正](https://github.com/hajimehoshi/ebiten/commit/5eb77d2fb5cf71fe966d11010f5b1d81a338a111)

デスクトップや Android の描画先フレームバッファは 0 (デフォルトフレームバッファ) であり、何も考えずにそこに描画していたのだが、 iOS は 0 は使えないことが判明。ロジックを変更する必要に迫られた。これに気づくまで画面真っ暗である。

### [フレームバッファの大きさを考慮にいれたスケールの計算 (後に撤廃)](https://github.com/hajimehoshi/ebiten/commit/83ab4352f852eeef37ab62beb1997639c5453aa8)

iOS の描画先のフレームバッファのサイズは GL surface view の大きさとは一致せず、ちゃんと考慮してスケールを計算しないと駄目だった、と記憶している。後にちゃんとしたスケールを計算するように修正したので、この処理は不要になった。

### [glBindFramebuffer の度に glViewport を呼ぶ修正](https://github.com/hajimehoshi/ebiten/commit/bc2703c345c7791ff781be263a0c7221cba8de78)

Ebiten は `glViewport` に指定する値が毎度同じなので最初の 1 回以外は全部すっ飛ばしていたのだが、どうも iOS の場合は `glBindFramebuffer` の度に呼び出す必要が有ることが判明。 OpenGL は難しいですね…。

## 2016-06-19

### [iOS におけるスケールの取得](https://github.com/hajimehoshi/ebiten/commit/6f50ef360498b1519295c0ebe348f5493a39b19b)

UIKit から画面のスケールを取得。 Objective-C を cgo 経由で呼び出した。

## 2016-06-21

### [iOS のタッチの実装](https://github.com/hajimehoshi/ebiten/commit/2ba3fd06073c7bdc7f94f5dc15647f0c7050f315)

Ebiten は `gomobile build` ではなく `gomobile bind` で動的ライブラリを生成することでモバイルでの利用が可能になる。 `gomobile bind` を使う以上 Ebiten 内部でタッチの状態の取得は不可能なので、 Objective-C 側からタッチの状態を渡してあげる必要がある。なお Android も同じである。

## 2016-06-22

### [iOS で `glViewport` を毎フレーム呼ぶように修正](https://github.com/hajimehoshi/ebiten/commit/e9de66aca2007a679de4ba11ea14ef061dca2f6e)

iOS は glViewport を毎フレーム呼ばなきゃいけないそうです。

### [`glViewport` を呼ばなきゃいけない条件を緩和](https://github.com/hajimehoshi/ebiten/commit/56c4e7185907f654bd7b3c6dc4c9659a0f5fb13e)

実は「iOS ではフレームバッファが変わったら必ず `glViewport` を呼ばなきゃいけない」というのは間違いで、大きさが変わったタイミングで呼べばいいことが判明 (どうして判明したかは忘れた)。無駄に `glViewport` を呼ぶのはパフォーマンス上問題なので削除することに。

## 2016-06-23

### [GLSL で `mat4` 同士の `==` 比較をしないように修正](https://github.com/hajimehoshi/ebiten/commit/24bb5b5ca88278275ad0c9808f105aff92d6aa74)

いままで当たり前のように `mat4` 同士を `==` で比較していたのだが、実はこれは定義されていないことがわかり、削除。 iOS で発見されたが、なんで他のデバイスでこれが問題にならなかったんですかね…。

----

ここまでやってもまだ iOS での描画がおかしい。次回へ続く。

# ライセンス

この記事のライセンスは [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) とします。