2015/11/25
GLSLで書いたシェーダーをUnityのマテリアルにセット、WebGL出力してみます
Unityでシェーダーを書く機会は中々ありませんでしたが、今後のためにもGLSLでシェーダーを書いてみます。
GLSLの特徴はOpenGLに使えるという点です。ということは、スマートフォンゲームやWebGL(ブラウザ)に応用することもできます。 また、言語的には、ほぼCに近い、ポインタのないC言語といった印象があります。(今回、細かな言語仕様の説明は割愛させていただきます。)
まずはGLSL on ブラウザで書く
まずは純粋にGLSLのフラグメントシェーダーだけを書いて試してみたいと思います。 これにはGLSL Sandboxというサイトを使います。このサイトでは、WebGL経由でシェーダーのGLSLコードをリアルタイムプレビュー、さらにjsdoitのようにギャラリーやフォークなどもできます。先にここで書く理由は、ちょっと寄り道してみたかったからです。w WebでもUnityでもどっちでも動くと良いですし。
ちなみに、GLSL Sandboxの開発にはthree.jsの@mrdoob氏など、著名開発者が名を連ねています。
凝ると際限がないと思いますが、そこそこ見栄えしてきたら次のステップへいきます。
デモはこちら : http://glslsandbox.com/e#29054.0
ソースは以下の通りです。
ポイントは(というほどではありませんが・・)
時間経過を元にして三角関数を動かしているところです。
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 resolution;
void main( void ) {
vec2 position = ( gl_FragCoord.xy / resolution.xy ) - 0.5 ;
vec3 col = vec3(0.0,0.0,0.0);
// 15個円を描く
for(int i = 0; i < 15; i++){
float red = 0.01 / abs(length(position + float(i) * 0.1) - 1.0 * abs(sin(time))) ;
col.r += red;
}
// 時間変化に合わせて色を変える
col.g = abs(cos(time));
col.b = abs(sin(time));
gl_FragColor = vec4( col , 1.0 );
}
シェーダーのコードをUnityのマテリアルに持っていく
さて、フラグメントシェーダーのアルゴリズムができたので、Unityのマテリアルを作ってシェーダーをセットしていきます。
ここらへんは以下のページが非常に参考になりました。
「Unity で GLSL によるカスタムシェーダを利用する方法」
http://tips.hecomi.com/entry/20130324/1364136769
マテリアルを作って・・・
シェーダーを作って・・・
シェーダーを書いていきます。
GLSL SandboxのコードをUnity用にする。
先の参考ページをもとにシェーダーのコードを書いていきます。 というか、書いていて気づいたんですがUnityはシェーダーの変更があった場合、リアルタイムに反映してくれるんですね。こりゃ知らなかった。。良いですね。
出来上がったシェーダーはこちら
Shader "Custom/GLSL Shader" {
SubShader {
Pass {
GLSLPROGRAM
#ifdef VERTEX
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
uniform vec4 _Time;
uniform vec4 _ScreenParams;
void main()
{
vec2 position = ( gl_FragCoord.xy / _ScreenParams.xy ) - 0.5 ;
vec3 col = vec3(0.0,0.0,0.0);
float time = _Time.x * 15.0;
for(int i = 0; i < 15; i++){
float red = 0.01 / abs(length(position + float(i) * 0.1) - 1.0 * abs(sin(time))) ;
col.r += red;
}
col.g = abs(cos(time));
col.b = abs(sin(time));
gl_FragColor = vec4( col , 1.0 );
}
#endif
ENDGLSL
}
}
}
ここまでで、こんな感じです。(それっぽいcubeを足しました)
いよいよ再生・・・
こうなりました・・・!!
先ほどのシェーダーが壁一面に広がっています。
動いたので、UnityからWebGL出力
さて、エディター上では一通り、それなりの動きを見ることができました。 次はUnityからWebGL出力をします。これでブラウザ上で上手くシェーダーが動けばいいんですが・・・
書き出してしばし待機・・・
圧縮されてはいますが、動きました!
モバイルブラウザでも動くの?
ちなみに、iOS9.1で動くのかも試してみましたが・・・
動きませんでした。まだ動かないかー。Android5.1でも動きませんでした。
しかも、こんなアラートも出ています。
「まだUnityはWebGL出力をサポートしていないけどいいの?それでもいいならOKを押してくれたって構わないが・・」という相変わらずの内容です。当然OKを押しましたが、動きません。
モバイル対応の道はまだまだのようです。詳しい情報をご存知の方はお教えいただければと思います。
結果
GLSLで書いたシェーダーを、UnityのWebGL出力で、PCブラウザでは動かすことができました!(モバイルブラウザでは不可)
シェーダーを書くと、画面の表現力が一段増す感じがしますね。