【Unity】【シェーダテクニック】0~1の値の強度をpow()を使わずに変換する

Unityのシェーダで0~1の値の強度をpow()を使わずに変換する方法です。

Unity2019.2.10

やりたいこと

いま、シェーダで0~1を取る値があるとします。

f:id:halya_11:20191222184108p:plain

これを、何らかの関数を用いて非線形の値に変換することを考えます。

f:id:halya_11:20191222184147p:plain

このような場合、シェーダではよくpow関数を使います。

float dst = pow(src, x);

この形式はフォン反射などでも使われます。
ただ、この計算式は入力値がマイナスであるほど結果が大きくなったりピーキーな部分があったりとイマイチ直感的ではありません。

f:id:halya_11:20191222184334p:plain

特に入力値をマテリアルプロパティとして外から見えるように実装する場合にはもっと直感的な調整を可能にするべきです。
そこで本記事ではもう少し直感的な関数を作ってみます。

pow()より直感的に調整できる関数

前節の課題を解消するため、dst = src - (src - src * src) * -xという関数で変換を行います。
これを適用すると以下のようなグラフが得られます。

f:id:halya_11:20191222184655p:plain

上図を見るとわかる通り、-1に近づくほど下に凸な、1に近づくほど上に凸なグラフになっているので直感的です。
また、ピーキーな部分もなく、pow()を使っていないため処理負荷もそこまで大きくはありません。

ただし大きく凸になるようなカーブは作れないので、その点は使いどころが限られそうです。

ちなみに一応、シェーダで書くとこんな感じです。

float curve(float src, float factor) {
    return src - (src - src * src) * -factor;
}
float2 curve(float2 src, float factor) {
    return src - (src - src * src) * -factor;
}
float3 curve(float3 src, float factor) {
    return src - (src - src * src) * -factor;
}
float4 curve(float4 src, float factor) {
    return src - (src - src * src) * -factor;
}