Technology Blog

技術ブログ

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氏など、著名開発者が名を連ねています。

凝ると際限がないと思いますが、そこそこ見栄えしてきたら次のステップへいきます。

29g51155224222

デモはこちら : 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

マテリアルを作って・・・

スクリーンショット 2015-11-25 18.21.19

シェーダーを作って・・・

スクリーンショット 2015-11-25 18.22.12

シェーダーを書いていきます。

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を足しました)

スクリーンショット 2015-11-25 18.32.26

いよいよ再生・・・

こうなりました・・・!!
先ほどのシェーダーが壁一面に広がっています。

29g511552242228

動いたので、UnityからWebGL出力

さて、エディター上では一通り、それなりの動きを見ることができました。
次はUnityからWebGL出力をします。これでブラウザ上で上手くシェーダーが動けばいいんですが・・・

書き出してしばし待機・・・

圧縮されてはいますが、動きました!

スクリーンショット 2015-11-25 18.48.59

デモはこちらになります。

モバイルブラウザでも動くの?

ちなみに、iOS9.1で動くのかも試してみましたが・・・
動きませんでした。まだ動かないかー。Android5.1でも動きませんでした。
しかも、こんなアラートも出ています。

IMG_0537

「まだUnityはWebGL出力をサポートしていないけどいいの?それでもいいならOKを押してくれたって構わないが・・」という相変わらずの内容です。当然OKを押しましたが、動きません。

モバイル対応の道はまだまだのようです。詳しい情報をご存知の方はお教えいただければと思います。

結果

GLSLで書いたシェーダーを、UnityのWebGL出力で、PCブラウザでは動かすことができました!(モバイルブラウザでは不可)
シェーダーを書くと、画面の表現力が一段増す感じがしますね。


関連ブログ