Skip to content

シェーダー芸(GPUパーティクル)入門~逆引編

Posted in 技術記事

概要編ではシェーダによるGPUパーティクルについて、大まかな内容を説明しました。
今回は勉強を進める上で、主に他人のコードを見た時に疑問に思いやすそうな部分を列挙してみます。

全体的な部分

数学を避けることはできますか?

無理です。
他人のコードを移植する程度のことはできますが、自由に軌道を作るには少なくとも高校程度の知識は必要です。

汎用性のある知識ですか?

Geometryについてはあまりありませんが、シェーダを読めることや数学については大いにあります。
シェーダといえばほぼVertexとFragmentを指し、Geometryは限定的な用途になるためです。
Unity5.6.3p1しか使えないVRChatという状況においてのみParticleSystemに対して優位を取れています。しかしParticleSystemもGPUサポートを始めていたり、Orbital(軌道)の設定が増えたりと、VRChatの対応如何ではすぐに覆ることは知っておいたほうがいいでしょう。

エディタの補完機能が欲しい

VSCodeであればShaderlabVSCodeという拡張機能があります。

シェーダの使い方

パーティクルが少ない

ポリゴン数の多い3Dモデルに適用しましょう。Unity標準だとSphereやPlaneがオススメです。
Gemetryシェーダでは、シェーダを適用したポリゴンと等しい数のパーティクルを生成します。

コードの書き方(全体)

float3とかfloat4x4って何…?

float値の指定個数セットです。
float3ならばfloat値3つ、float4x4ならば全てがfloat値の4*4行列を表します。float3はunity C#でいうtransform.positionを想像すると分かりやすいと思います。

float3 hoge3 = float3(1,2,3);

float3やfloat4の扱い方①

unity C#でいうvecter3やcolorのように扱えます。

float4 hoge4 = float4(1,2,3,4);
float z = hoge4.z; //zは3となる

float3やfloat4の扱い方②

メンバーはx,y,z,wが割り当てられており、組み合わせてfloat2や3を作る事もできます。

float4 hoge4 = float4(1,2,3,4);
float2 z = hoge4.zw; //zはfloat2(3,4)となる

float3やfloat4の扱い方③

式の途中に混ぜ込んでもかなり柔軟に処理してくれます。
(どちらかというと関数側の機能ですが)最初は面を喰らうだろう仕様であり、知らないととても読みにくい仕様。

float2 xy = float2(1,2);
float4 hoge4;
hoge4 = float4(xy,3,4); //問題ない、下と同じ結果
hoge4 = float4(1,2,3,4);
xy = cos(xy); //問題ない、下と同じ結果となる
xy = float2(cos(xy.x),cos(xy.y));

frac(sin(dot(co.xy, float2(12.9898,78.233))) * 43758.5453)って何?

よく使われる乱数生成機で0-1の間の値を取ります。
こういうものだと思って使えば大丈夫です。

Propertiesで指定した変数が使えない

pass内でも宣言する必要があります。

Properties {
_TimeScale ("Time Scale", Float) = 1.0
}
SubShader{
pass{
//中略
float _TimeScale;
}
}

UNITY_MATRIX_*って何?

座標変換を行うための行列です。
シェーダでは最終的に画面のxy座標に変換しないとモデルを映すことができません。そのための定数がこの値で、1回ずつ使わないと思ったような出力になりません。
何をしているか把握出来ると、全体の移動や回転など、調整が簡単になる処理があります。
参考資料:チュートリアル3:行列 – opengl tutorial

float3 pos;
pos = mul(UNITY_MATRIX_M,pos); //モデル→ワールド座標変換
pos = mul(UNITY_MATRIX_V,pos); //ワールド→ビュー座標変換
pos = mul(UNITY_MATRIX_P,pos); //ビュー→ディスプレイ座標変換
//M,V,Pと1回ずつ変換をする必要があります
//複数一度に処理するためのUNITY_MATRIX_MVPやVPといったものも用意されています
mul(UNITY_MATRIX_MVP, float4(pos, 1.0))
UnityObjectToClipPos(pos) //上の式と等価です。こちらの方がパフォーマンスがいいようです。

コードの書き方(軌道)

この数値は何を表しているの?

お気持ちです。冗談半分ですがもう半分は本気で言っています。
GPUパーティクルは、まず規則的な動きを作り、そこに乱数などを使って自然に見えるようにしていく、という作り方をすることが多いです。なので、「適当に数字を加えたらいい感じになった!これでOK!」という数字が残っていることはよくあることなのです。

cos?sin?floor?sqrt?pow?

数学の関数です。
ここは都度調べていくようにしましょう。以下の資料が参考になります。

Be First to Comment

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です