GLSLにiChannelResolution（配列のuniform）を渡す＜細かすぎ？＞

###GLSLにiChannelResolution（配列のuniform）を渡す＜細かすぎ？＞
openFrameworks用のShadertoyのアドオンofxShadertoyを使って、shadertoy.com上のコードを
移植していたら、そのままでは動かないケースがままある。今回は、
***"iChannelResolution"***
たとえば、https://www.shadertoy.com/view/3dlfWs 
などでは、ちゃんとした表示にならない。
↓こうなるべきところが、
(openframeworksのofxShadertoで表示)
![out000012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/3af3db8f-768b-e38b-9b47-ae8c9ce32e6f.png)

↓こうなる。
![out000012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/bb5a8407-58cf-4382-8472-6c0baf634cad.png)


ShadertoyのA,B,C,Dバッファにはそれぞれ4チャンネルのテクスチャーを登録できるチャンネルが
あるが、iChannelResolutionは、そのテクスチャーの縦横ピクセル数が入っている変数で、
現在のofxShadertoyではサポートされていない。
たとえば、https://www.shadertoy.com/view/XlBBRR
なども、以下のようにコードにiChannelResolution[0].xy　を含むので、動作しない。
しばらく何故動かないのかわからず、放置しておいた。

```
#define rndB(U) texture(iChannel0, U)     // bilinear interpolation

vec4 rndC(vec2 u) {                       // bicubic interpolation ( 1 single fetch: thanks iq :-) )
    vec2 R = iChannelResolution[0].xy,
         U = u*R + .5,
         F = fract(U);
    U = floor(U) + F*F*(3.-2.*F); 
 // U = floor(U) + F*F*F*(F*(F*6.-15.)+10.);   // use if you want smooth gradients
    return texture( iChannel0, (U-.5) / R );
}

void mainImage( out vec4 O, vec2 U )
{
    vec2 R = iResolution.xy, V;
    U = ( U+U - R ) / R.y;
    V = .1*( U - .1*iTime );
    
	O =   U.y > 2./R.y ? rndC(V)          // bicubic (null-tangent)
        : U.y > 0.     ? vec4(14) 
        :                rndB(V);         // bilinear
    if (U.x>0.) O = sin(10.*O);
  //O = sqrt(O);                          // gamma correction
}

```

ちゃんと動作すれば、以下のような表示になる。

![out000020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/207ab04c-d0c2-f670-926e-f2d4eea0c932.png)

 iChannelResolutionを認識するために以下のようにofxShadertoyのソースコードを変更する。
先ず、ofxShadertou.hに***bool isChannelBind;***を追加し、
ofxShadertoy.cpp内で、

***if (channels[(size_t)buffer][0].isAllocated() && !isChannelBind) {***
を検索して、これを、以下のようにする。(03/28に修正）

```
if (channels[(size_t)buffer][0].isAllocated() && !isChannelBind[(size_t)buffer]) {
		channels[(size_t)buffer][0].bind();
		// HI channel0の入力の解像度iChannelResolutionをストア
		//if (channelRes) { // 最初の一回だけ
		isChannelBind[(size_t)buffer] = true;
		ofVec2f vc[4];
		for (int i = 0; i < 4; i++) {
			vc[i] = ofVec2f(float(channels[(size_t)buffer][i].getWidth()), float(channels[(size_t)buffer][i].getHeight()));
		}
		// 3x4 のfloat配列をまとめる
		float vecf[12] = { vc[0].x, vc[0].y, 0.0, vc[1].x, vc[1].y, 0.0, vc[2].x, vc[2].y, 0.0, vc[3].x, vc[3].y,0.0 };
		// uniformでglslプログラムに送る iChannelResolution[4];
		bufShader.setUniform3fv("iChannelResolution", vecf, 4);

	}
```
　これで、iChannelResolutionが機能し、Shadertoyのコードがそのまま動作する。
（isChannelBindは、どこかで初期化してください。）
isChannelBind[0] = false;
isChannelBind[1] = false;
isChannelBind[2] = false;
isChannelBind[3] = false;
ここでfloatの値を配列に並べて、***bufShader.setUniform3fv("iChannelResolution", vecf, 4);***
でシェーダーに渡しているが、これが正解なのかどうか自信はないが一応動作している。

###また、忘れてました。
ofxShadertoy.cppShadertoy.cpp
内で、
bool ofxShadertoy::makeShader(std::string const & textBuffer, ofShader & outShader) {
を検索し、
string fragprogram =
		string
以下に
***"uniform vec3       iChannelResolution[4];\n"***
を追加します。