こんにちは、Unityエンジニアのオオバです。

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

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

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

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

今回参考にした、煙がゆっくり流れるようなGLSL Sandboxの作品
GLSL Sandbox

変換後のシェーダーソース(Cg/HLSL)はコチラ
Smoke1.shader · GitHub

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

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

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


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

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);  

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

👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!

もくじ

まとめ

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

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

iOS向けプロダクトであれば実機ビルドしてGPU負荷を見るのも良いかもしれません。

オススメ記事
検証環境