CocosCreator v2.1.1でシェーダーを使う

# 初めに
色々あってCocosCreatorを触る事になったのですが、
**日本語ドキュメントが圧倒的に少ない！**
**参考書が圧倒的に少ない！**
という事で、実装以前の問題でハマる事が多々ある状況です。

そこで、同じ轍を踏む人が少しでも減ればと思い記事を書かせて頂きました。

# v2.1.1版でシェーダーが動かない
CocosCreatorを触っている方でしたらご理解頂けると思うのですが、
バージョンによりメソッドが消えたり挙動が大きく変わったりと中々難儀な子です。

シェーダーについてもv2.0で大幅な変更がかかったそうです。
https://discuss.cocos2d-x.org/t/what-happened-with-cc-glprogram/44539

その時の[解決策](https://github.com/ShawnZhang2015/ShaderHelper)についてもv2.1.1版ではプロジェクトの実行すら出来ない状態。
過去は振り返らないそのお姿、素敵です。 ~~現場は阿鼻叫喚です。~~


# 答えは意外と身近にあった
結論から言いますと、シェーダーは「Effect」というファイルにプログラムを記載する形になったようです
右クリック→「Create」の一覧にしれっと存在していました。

- Effectファイル作成及び編集
- MaterialにEffectファイルを登録
- SpriteにMaterialをセット

以上でシェーダーを反映することが出来ます。

# 実際にやってみる
### 画像の用意
分かりやすいようにRGBそれぞれが255の3色画像を作成
![rgb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/0dc59b14-085c-b22a-5b8c-cd0def5e96b1.png)

### Effectファイルの作成
![effect1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/6dc33816-b340-7e1e-8787-7db7f48c7b2b.png)
今回は良くある灰色にするシェーダーを作成するので、「Gray」というファイル名にしました。

作成したファイルはテキスト形式なのですが、
JSやTSファイルのように自動でエディタが起動しないため、手動でファイルを開いて下さい。

```glsl:Gray.effect
/**
 * 灰色シェーダー
 */

%{
	techniques : [
		{
			passes : [
				{
					vert : vs
					frag : fs
					cullMode : none
					blend : true
				}
			]
			layer : 0
		}
	]
	properties : {
		texture : {
			type : sampler2D
			value : null
		}
	}
%}

%% vs {
	uniform mat4 cc_matViewProj;

	attribute vec4 a_position;
	attribute vec2 a_uv0;
	attribute vec4 a_color;

	varying lowp vec4 v_fragmentColor;
	varying mediump vec2 v_texCoord;
	
	void main() {
		gl_Position = cc_matViewProj * a_position;
		v_fragmentColor = a_color;
		v_texCoord = a_uv0;
	}
}

%% fs {
	precision lowp float;

	uniform sampler2D texture;

	varying vec4 v_fragmentColor;
	varying vec2 v_texCoord;

	const vec3 grayScale = vec3(0.298912, 0.586611, 0.114478);

	void main() {
		vec4 color = v_fragmentColor * texture2D(texture, v_texCoord);

		float grayScaleColor = dot(color.rgb, grayScale);
		gl_FragColor = vec4(vec3(grayScaleColor), color.a);
	}
}
```
RGB値の重みが異なるのは**NTSC加重平均法**と言って、白黒テレビで使われていた規格によるものらしいです。
もしもRGB値を同じ重みにした場合、今回使用した画像は3色とも同じ濃さになってしまうため、
人の明るさの感じ方を考慮した配分になってます。

### Material作成
![effect2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/68c0fa36-492f-53dd-adf3-3a6a952a7026.png)
Materialを新規作成し、名前を「Gray」に

![effect3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/3ec5daec-a37e-0659-85cc-ad1721ec1de5.png)
先ほど作成したGray.effectを設定
textureは何も入れなくてOKです。

### Script作成
ちゃちゃっと確認出来るように簡易的なScriptを組みます

```Gray.ts
const {ccclass, property} = cc._decorator;

@ccclass
export default class Gray extends cc.Component {

	@property({
		// @ts-ignore
		type: cc.Material,
		displayName: "Material",
		tooltip: "マテリアル"
	})
	material = null;

    start () {
        let sprite = this.node.getComponent(cc.Sprite);
        sprite.setMaterial(0, this.material);
    }
}
```
![effect4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/5539282c-9132-37d8-3bbf-770262f909ba.png)

### 実行結果
![gray.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57874/5c26306e-0203-cc78-2364-32328eaa080c.png)
灰色になりました！
RGBもそれっぽくなってますね。

# 補足
effectファイルの中身についてですが、uniform,attributeで使える変数名で少しハマりました。
こちらはCocosCreator本体側にある
enums.js
forward-renderer.js
に記載されています。

# 最後に
Cocosはクセが強いですが、Unityと比べてWeb版での起動が早い、メモリ消費が少ないというメリットがある事と
最近は[HTML5のゲーム](https://enza.fun/)も増えてきているので、
Webブラウザをメインとするゲームなどでは選択肢としてアリだと思います。
後はVFXツールが充実すると良いのですが・・・。