渋谷ほととぎす通信

完全趣味でやってるUnityメモ。説明できないところを説明できるようにするための個人ブログ。昨日の自分より少しでも大きくなれるように。。。 ※所属団体とは一切関係がありません

GLSL SandboxをUnityに移植する方法その2


環境

  • Unity5.5.0p1

前回に引き続きGLSL Sandbox作品をUnityに移植して遊んでみる記事です。

www.shibuya24.info

前回はGLSL Sandbox初期シェーダコードでしたが、今回は色々と変更が入った作品を例に遊んでみます。

f:id:esakun:20161213211829p:plain

今回参考にした、煙がゆっくり流れるようなGLSL Sandboxの作品
http://glslsandbox.com/e#37255.0

変換後のシェーダソース(Cg/HLSL)はコチラ
gist.github.com

※不要そうなソースコードは削除されています。またパフォーマンスの観点からfloat、fixed型をhalf型に変更しています。

f:id:esakun:20161213215432g:plain

このような感じの成果物が出来ました。


ここから変換する上で何点かポイントを挙げます。

1. vert_img関数の使用

GLSL Sandboxはフラグメントシェーダのみで完結しているサービスなので頂点シェーダは、座標変換後の頂点をフラグメントシェーダに渡すだけで良いです。
そこで頂点シェーダにvert_imgを指定します。

CGPROGRAM
#pragma vertex vert_img

vert_imgはUnity側が用意しているUnityCG.cgincインクルードファイル内で定義された関数です。

◆UnityCG.cgincの一部ソース

...

struct appdata_img
{
    float4 vertex : POSITION;
    half2 texcoord : TEXCOORD0;
};

struct v2f_img
{
    float4 pos : SV_POSITION;
    half2 uv : TEXCOORD0;
};

v2f_img vert_img( appdata_img v )
{
    v2f_img o;
    o.pos = UnityObjectToClipPos (v.vertex);
    o.uv = v.texcoord;
    return o;
}

...

このようにvert_img関数を使用すると、上記の定義済み構造体を使用し、座標変換後の頂点をフラグメントシェーダに渡してくれるので非常に便利です。

half4 frag (v2f_img i) : SV_Target {
    // fragment shader content
}

一方フラグメントシェーダは v2f_img型引数を定義しておくだけです。

2. vecとhalf, fixed, float型の違い

vec3 a = vec3(1.0);

というGLSLソースを、

half3 a = half3(1.0);

Cg/HLSLでこのように書いてはいけません。コンパイルエラーになります。

half3 a = half3(1.0, 1.0, 1.0);

正解はこちら。
このように引数を省略することは出来ません。

まとめ

GLSLからCg/HLSL移植に関して、処理内容が難解なものはありますがルールと作法さえ理解すれば、変換自体はそこまで難しくはありません。

ただし実際のプロダクトで使用する場合はパフォーマンス改善をしないと厳しい場合が多いです。
ほとんどの作品がフラグメントシェーダ内でsin, cosなどの関数を大量に使用しているため、GPU負荷は非常に高いと思われます。 使用する場合はご注意を。

iOS向けプロダクトであれば実機ビルドしてGPU負荷を見るのも良いかもしれません。
※傾向程度であればUnityProfilerでも把握できるかと思います。

あわせてどうぞ

www.shibuya24.info

www.shibuya24.info

www.shibuya24.info

www.shibuya24.info

www.shibuya24.info