fc2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »グラフィックス
このページの記事一覧

【Unity】【C#】Light の Halo はランタイム操作できない?  


 現在 VRMLiveViewer v3.8 に入れるカスタムなライトを実装中…。せっかくなので、Light コンポーネントの細かい機能も操作できるようにしたいと思って、色々調べていたが、どうやらインスペクタにある DrawHalo はスクリプトから操作できないようだ…(プロパティ自体が無い)。

 不思議に思ってググっていたら、なぜか Halo は public な機能ではないらしいね。予め設定したものをビルドして使うだけのものなのか…?

 また、Light 内の DrawHalo ではなく、別コンポーネントの Halo (インスペクタで個別にアタッチするやつ) でオン/オフするコードが出てきた。しかしそれもやはり少し変わっていて、Behaviour クラスを用いて enabled を true/false してるね。まぁ、一応成功したので、コードだけ載せておこう。

(※) Unity 2020.3.34f1 / Windows11(x64) で確認

●アタッチした Halo コンポーネントをオン/オフするコード
using System;
using UnityEngine;

public static partial class Extensions //※クラス名は任意
{
public static void SetEnableHalo(this Light light, bool isOn)
{
if (light == null)
return;

var halo = (Behaviour)light.gameObject.GetComponent("Halo"); //Behaviour 型
//var halo = light.gameObject.GetComponent("Halo"); //Component 型
if (halo != null)
{
halo.enabled = isOn; //Behaviour 型
//halo.GetType().GetProperty("enabled")?.SetValue(halo, isOn, null); //Component 型
}
}
}

●スクリプトからの使用例
using UnityEngine;

public class SetEnableHaloTest : MonoBehaviour
{
public Light _light; //インスペクタでアタッチしておく

//Button の OnClick 等からコールバックする
public void HaloOnClick()
{
_light.SetEnableHalo(true);
}

//Button の OnClick 等からコールバックする
public void HaloOffClick()
{
_light.SetEnableHalo(false);
}
}

 SetEnableHalo 内ではコメントアウトで Component 型のコードも書いてあるが、どちらでもいけるようだ。ただこれはインスペクタで予め Halo コンポーネントを追加しておくか、コードで AddComponent("Halo") しなければならない。型指定にはジェネリック型 <Halo> は使えないようだ。GetComponent も同じ。なぜか名前(文字列)でしか指定できないらしい。以下の参考資料(UnityCsReference)に「internal sealed partial class Halo : Behaviour」となっているので(public ではないので)、そのせいか?

(参考資料)
UnityCsReference/Runtime/Export/GraphicsComponents.bindings.cs
Getting the Halo property of a point light in Unity
How can I change the value of 'Draw Halo' inside Point Light - Unity3D
Enable Draw Halo in Light Component via Script



 結局、オン/オフはできても色や距離の変更はできないので(やはり public なプロパティが無いので)、実装自体をやめた。また、リフレクションでプライベートメンバーを取得するような方法もググってたら出てきたが、そもそも public でない時点でランタイム動作は保証されないので、使わない方が良い気がする。

 また同じ様な効果なら、Volumetric Light の方が綺麗だったしね。無理矢理やろうと思えば、予めビルドにオンとオフの2つの状態を別GameObjectにアタッチしておき、切り替える方法もあるが、それなら Light の DrawHalo でやった方が良いか気がする(Color と Range が自動的に連動するので)。ただそれほど有用でもないし、使い勝手も悪いので(コードが無駄に複雑になるので)、Halo 自体のランタイム操作は諦めた方が良いかな…。



(関連記事)
【Unity】Standard Assets の Flare (レンズフレア) は Gamma 用だった?
【Unity】【C#】指定ワールド位置がカメラに映っているか調べる
【Unity】【C#】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換


関連記事
スポンサーサイト



category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityリファレンス  Unityライブラリ  グラフィックス 
tb: 0   cm: --

【Unity】Standard Assets の Flare (レンズフレア) は Gamma 用だった?  


 たぶん Unity2018.3 頃からだと思うけど、デフォルトのシーンに FlareLayer がアタッチされなくなったんだよね。Standard Assets も既にレガシーとなっているので、今更とは思うのだが、ググっても LensFlare 系のフリーアセットってあまり出てこないので、改めて Standard Assets を試してみた。
 しかしう~ん…。なぜか私の記憶している感じと違う…。Unity5 の頃は Standard Assets は当たり前のように使ってたので、こんな感じの LensFlare じゃなかったような…。もっと綺麗に輝いていた気がするぞ…?


 どうにもしっくり来ないので、古い Unity5 のプロジェクトを開いてみた。そして同じように Standard AssetsLensFlare を使ってみると見た目が全然違う!


 比較してすぐに気づいたのは「Color Space の違い」なんだよね。Unity5 の頃は Gamma Color Space が普通に使われていたため、アセットも Gamma 用が普通だった。しかし Unity2018 以降は Linear Color Spane も Experiment(試験実装)的 ではなく、正式に採用されるようになっていったため、アセットも Linear 用(もしくは両対応)になっていった。以下の資料を見ても分かる通り、特に加算・合成といった処理では Color Space の違いがよく出るので、Standard AssetsLensFlare は Gamma 用だったと仮定すると説明がつく。

(参考) 分かる!リニアワークフローのコンポジット - 「加算が変わる」 参照

 ならばテクスチャの「Import Settings の sRGB を外せば、リニアでも使える」みたいなことを VRMLiveViewer での Color Space 移行(v2.x→3.0α時代) で学んでいたので、試してみた。う~ん、それでも太陽以外はぼやけて見えない感じだな…。


 そう言えば Flare asset 自体をあまり覗いたことなかったな~、と思って設定を見てみると Color プロパティがある。これも以前「ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換」として記事を書いていたように既に学んでいたことなので、Linear 上で Gamma っぽい色にする:つまり Linear → Gamma の Color 変換 を試してみた。そしたら、Color Space の違いから色味が異なるのは仕方ないにしても、それなりに近い感じになった!

Linear → Gamma の Color 変換

●色のプロパティを Gamma 変換してみる

※全ての Element の Color プロパティを同様に Gamma 変換する

●Unity2020.3上(Linear Color Space)での Flare アセットの Color 設定を Linear → Gamma 変換してみる

 最初の Unity5 の Gamma Color Space と比較してみると、やはり色の加算・合成的な部分で色味が異なるが(Gamma は色を重ねると輝きが強くなり、Linear は白っぽくなる傾向がある)、なるほど、Standard AssetsLensFlare は Gamma 用だったと言って間違いないようだ。


 まとめると、
・テクスチャの Import Settings の sRGB のチェックを外す
・Flare asset の各 Element の Color プロパティを Gamma 変換する

で、それなりに近い感じにできる(※カラースペースによる差異はどうしてもあるが)





(関連記事)
【Unity】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする
【Unity】Quality (グラフィック品質) を文字列で取得/設定する
【Unity】画面解像度とアクペクト比(整数)を求める
【HTML】HTMLカラー名・カラーコード表


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityリファレンス  Unityトラブルシューティング  グラフィックス 
tb: 0   cm: --

【Unity】【C#】HDR Color を計算(変換)する  


 現在の VRM Live Viewer にはパーティクルの発光色を設定できる機能があり、HDRカラーピッカーが実装されているのだけど、これを作ったときのメモ。

 そもそも Unity にはエディタ上で普通に HDRカラーピッカーが入ってるのだけど、なぜか API にはそういった Utility クラスが無いんだよね。なので、ググってたら、いくつか見つけたので、それを少しばかり使いやすくした例。

(参考) How to Get / Set HDR Color intensity


(※) Unity 2020.3.26f1 / Windows11(x64) で確認



■LDR Color と intensity → HDR Color に変換する

 参考資料を見てみると、どうやら HDR Color の計算は LDR Color の アルファを除いた RGB の各要素に 2 の intensity 乗(= 2intensity) を掛ければ良いようだ。実際にやってみたら、Unity エディタ上のカラーピッカーの色とも合致する。なので、変換する拡張関数を定義すると以下のようになる。

(参考) How to Get / Set HDR Color intensity

●LDR Color と intensity → HDR Color に変換する
using UnityEngine;

namespace Exsample
{
public static partial class Extensions //※クラス名は任意
{
/// <summary>
/// LDR Color と intensity → HDR Color に変換する
/// https://answers.unity.com/questions/1652854/how-to-get-set-hdr-color-intensity.html
/// </summary>
/// <param name="ldrColor">LDR Color</param>
/// <param name="intensity">輝度(intensity)</param>
/// <returns>HDR Color</returns>
public static Color ToHDRColor(this Color ldrColor, float intensity)
{
var factor = Mathf.Pow(2, intensity);
return new Color(
ldrColor.r * factor,
ldrColor.g * factor,
ldrColor.b * factor,
ldrColor.a
);
}
}
}

 これは参考資料をそのまま拡張メソッドにしただけである。intensity = 0 のときは 20 = 1 なので、元のままとなるね。2 の intensity 乗(= 2intensity) というのは、そういうものと覚えておけば良いだろう。

(参考) How to Get / Set HDR Color intensity



■HDR Color → LDR Color と intensity に分離する

 次は前述の HDR Color 変換とは逆で、HDR Color を LDR Color と intensity に分離する計算だ。といっても参考資料そのままでも良いので、ここでは少しだけ使いやすく、戻り値を Tuple 型(.NET 4.x)にして、表現の値を255値にした例を書いておこう。

●HDR Color → LDR Color と intensity に分離する
using UnityEngine;

namespace Exsample
{
public static partial class Extensions //※クラス名は任意
{
private const byte k_MaxByteForOverexposedColor = 191; //internal Unity const

/// <summary>
/// HDR Color を baseColor, intensity(exposure) に分離する (Tuple)
/// https://answers.unity.com/questions/1652854/how-to-get-set-hdr-color-intensity.html
/// ※overExposed = 255 を与えると直感的になる : (白) baseColor = RGBA(1.000, 1.000, 1.000, 1.000), intensity = 1
/// Unity デフォ = 191 で HDR Color ピッカーと同等 : (白) baseColor = RGBA(0.749, 0.749, 0.749, 1.000), intensity = 1.416925
/// </summary>
/// <param name="linearColorHdr">HDR Color</param>
/// <param name="overExposed">internal Unity const = 191 (デフォルト: 255)</param>
/// <returns>(LDR Color, intensity)</returns>
public static (Color32, float) DecomposeHdrColor2(this Color linearColorHdr, byte overExposed = 255)
{
Color32 baseLinearColor32 = linearColorHdr; //※暗黙変換には型が必要
var exposure = 0f;

var maxColorComponent = linearColorHdr.maxColorComponent; //※たぶん (r,g,b) 内で一番高い値 → 1f を超えてたら HDR となる

// replicate Photoshops's decomposition behaviour : Photoshopの分解動作を複製する
if (maxColorComponent == 0f || maxColorComponent <= 1f && maxColorComponent >= 1 / 255f) //1/255 = 0.003921568627451
{
exposure = 0f;
baseLinearColor32.r = (byte)Mathf.RoundToInt(linearColorHdr.r * 255f);
baseLinearColor32.g = (byte)Mathf.RoundToInt(linearColorHdr.g * 255f);
baseLinearColor32.b = (byte)Mathf.RoundToInt(linearColorHdr.b * 255f);
}
else
{
// calibrate exposure to the max float color component : 最大フロートカラーコンポーネントへの露出を調整します
var scaleFactor = overExposed / maxColorComponent;
exposure = Mathf.Log(255f / scaleFactor) / Mathf.Log(2f);

// maintain maximal integrity of byte values to prevent off-by-one errors when scaling up a color one component at a time
baseLinearColor32.r = Math.Min(overExposed, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.r));
baseLinearColor32.g = Math.Min(overExposed, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.g));
baseLinearColor32.b = Math.Min(overExposed, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.b));
}

return (baseLinearColor32, exposure);
}
}
}

//メインでは…
//var (baseColor32, intensity) = emissionColor.DecomposeHdrColor2(); //overExposed = 255

 コードも参考資料とほとんど変わらない。ただ、Unity エディタで HDRカラーピッカーを使っている時、Intensity の値を上げると、再び開き直した時、なぜか 191 になってるのが不思議だったが、どうやら内部の定数値「k_MaxByteForOverexposedColor = 191」が効いていたようだ。なので overExposed で 255 をデフォルトで与えることによって(RGB 要素で 255 を超えた場合の表現方法らしい)、より LDR Color が直感的になったので変更している。Unity エディタと同じにしたければ、overExposed = k_MaxByteForOverexposedColor (191) を引数に与えれば良い。元コードのコメントを読むと、191 は PhotoShop に合わせた値らしいが、色コード("#FFFFFF" のような形式)として扱う場合には、ちょっと使いづらいんだよね…。

(参考) How to Get / Set HDR Color intensity



■HDR Color から intensity のみを取り出す

 これは前述の HDR Color → LDR Color と intensity に分離する の縮小版みたいなものだ。実際に DecomposeHdrColor2() のコードの一部のみを抜き出した感じとなる。輝度(Intensity)だけ欲しいときなど、短く書けるので一応載せておこう(もちろん、DecomposeHdrColor2() を使って intensity だけを得ても同じ)。

●HDR Color → LDR Color と intensity に分離する
using UnityEngine;

namespace Exsample
{
public static partial class Extensions //※クラス名は任意
{
private const byte k_MaxByteForOverexposedColor = 191; //internal Unity const

/// <summary>
/// HDR Color から Intensity のみを取得する
/// https://answers.unity.com/questions/1652854/how-to-get-set-hdr-color-intensity.html
/// ※overExposed = 255 を与えると直感的になる : (白) baseColor = RGBA(1.000, 1.000, 1.000, 1.000), intensity = 1
/// Unity デフォ = 191 で HDR Color ピッカーと同等 : (白) baseColor = RGBA(0.749, 0.749, 0.749, 1.000), intensity = 1.416925
/// </summary>
/// <param name="hdrColor">HDR Color</param>
/// <param name="overExposed">internal Unity const = 191</param>
/// <returns>輝度(intensity)</returns>
public static float ExtractIntensity(this Color hdrColor, byte overExposed = 255)
{
var maxColorComponent = hdrColor.maxColorComponent;
var scaleFactor = overExposed / maxColorComponent;
return Mathf.Log(255f / scaleFactor) / Mathf.Log(2f);
}
}
}

 これは参考資料の最後にあるコードと同じ。これも DecomposeHdrColor2() と同じように、overExposed の引数を k_MaxByteForOverexposedColor (191) にすれば、Unity エディタ上の HDRカラーピッカーと同じ値になる。

(参考)
How to Get / Set HDR Color intensity







(関連記事)
【Unity】【C#】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  C#  グラフィックス 
tb: 0   cm: --

【Unity】【C#】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換  


 そろそろ UniVRM をアップデートしたいなぁ、と思ったけど、とうとう UniVRM0.79 以降はカラースペース(Color Space)をリニア(Linear)に統一するらしく、インポートしたら強制的に変更されるようになってしまった。

 VRM Live Viewer は3年前、Unity2017初期の頃からはじまったのだが、CRS ステージは Unity4, Crystal ステージは Unity5 時代のものを流用してるんだよね。なので、ガンマ(Gamma)スペースなのだ。

 まぁ、正直言って、特に Unity2018 以降の機能は Linear 依りになってきたので(なぜか今でも Unity のデフォは Gamma だが)、いずれ移行したいとは思ってたんだけどね。

 しかし、さすがにマイナーバージョンアップデートで、前後の互換性がないのはおかしいし(不具合にしか見えないため)、メジャーアプデとして考えていた。なので急遽移行を迫られる形になってしまった。でも Color Space 変更って、プロジェクト素材全てに影響するので、とてもじゃないけどすぐにはできないんだよね(見た目がかなり変わる)。

 なので、自動化できるところはスクリプトで変換などするために、色々調べることになった。これはそのメモ。ほぼ出典そのままだが、汎用的に使えるので掲載しておこう。


(※) Unity 2019.4 / Windows10(x64) で確認



■Unity の Color, Mathf での変換

 ちなみに、Unity では Color 構造体が linear, gamma というプロパティがあり、Mathf には Mathf.GammaToLinearSpace, Mathf.LinearToGammaSpace という関数があるので、簡単に変換できる。例えば以下のようにできる。

using UnityEngine;

//ガンマ→リニア
var gammaColor = new Color(0.3f, 0.4f, 0.5f);
var linearColor = gammaColor.linear; //→ RGBA(0.073, 0.133, 0.214, 1.000)

var linearValue = Mathf.GammaToLinearSpace(0.5f); //→ 0.2140411ff

//リニア→ガンマ
var linearColor = new Color(0.073f, 0.133f, 0.214f);
var gammaColor = linearColor.gamma; //→ RGBA(0.300, 0.400, 0.500, 1.000)

var gammaValue = Mathf.LinearToGammaSpace(0.2140411f); //→ 0.5f

 これで事足りてしまう場合は良いのだが、もう少しつっこんだ実装をしたいとか、高速化した近似式を使いたいというときもあるだろう。それらは以降のようになる。



■汎用的な値(0~1f:正規化した値)での変換

●定義からの厳密な Gamma - Linear 相互変換 (0~1f:正規化した値での計算)
using UnityEngine;

/// <summary>
/// ガンマ(sRGB)→リニア (0.0-1.0:正規化した値) 色空間変換 (厳密なコード)
/// (参考)
/// https://en.wikipedia.org/wiki/SRGB
/// https://tech.cygames.co.jp/archives/2339/
/// </summary>
/// <param name="gamma">0.0-1.0</param>
/// <returns>0.0-1.0</returns>
public static float ToLinearValueStrict(this float gamma)
{
if (gamma <= 0.04045f)
{
return gamma / 12.92f;
}
else
{
return Mathf.Pow((gamma + 0.055f) / 1.055f, 2.4f);
}
}

/// <summary>
/// リニア→ガンマ(sRGB) (0.0-1.0:正規化した値) 色空間変換 (厳密なコード)
/// (参考)
/// https://en.wikipedia.org/wiki/SRGB
/// https://tech.cygames.co.jp/archives/2339/
/// </summary>
/// <param name="linear">0.0-1.0</param>
/// <returns>0.0-1.0</returns>
public static float ToGammaValueStrict(this float linear)
{
if (linear <= 0.0031308f)
{
return linear * 12.92f;
}
else
{
return 1.055f * Mathf.Pow(linear, 0.4166666f) - 0.055f; //0.4166666f = 1/2.4
}
}

 ここでは sRGB とガンマを同等に扱っているが、実際にはガンマ補正はディスプレイや機器などで値が違うようなので、あくまで一般的な仕様に合わせたものだと思って欲しい。

 式は以下の参考資料そのままだ。定義は Wikipedia に掲載されている。

(定義) sRGB (From sRGB to CIE XYZ, From CIE XYZ to sRGB)
(参考:式) 物理ベースレンダリング -リニアワークフロー編



●高速化近似式 (2.2乗, 1/2.2乗) での変換

 また、式の参考ページにも記載されているが、高速化用の近似式は以下のようになる。

●高速化近似式 Gamma - Linear 相互変換 (0~1f:正規化した値での計算)
using UnityEngine;

/// <summary>
/// ガンマ(sRGB)→リニア (0.0-1.0:正規化した値) 色空間変換 (高速化近似式: 2.2乗)
/// (参考) https://tech.cygames.co.jp/archives/2339/
/// </summary>
/// <param name="gamma">0.0-1.0</param>
/// <returns>0.0-1.0</returns>
public static float ToLinearValueFast(this float gamma)
{
return Mathf.Pow(gamma, 2.2f); //or 2.233333f
}

/// <summary>
/// リニア→ガンマ(sRGB) (0.0-1.0:正規化した値) 色空間変換 (高速化近似式: 1/2.2乗)
/// (参考) https://tech.cygames.co.jp/archives/2339/
/// </summary>
/// <param name="linear">0.0-1.0</param>
/// <returns>0.0-1.0</returns>
public static float ToGammaValueFast(this float linear)
{
return Mathf.Pow(linear, 0.45454545f); //1/2.2
}

 なぜそうなるのかというのは、以下を参照すると良いだろう。とてもわかりやすく解説されている。

(参考資料)
ガンマ補正のうんちく
分かる!リニアワークフローのコンポジット

 まぁ端的に言うと、曲線が似てれば、値も似るということだね(笑)。英語では「Magic Number」みたいにも言われている。

 ちなみに、冒頭に書いた Unity の Color.linear や Color.gamma, Mathf.GammaToLinearSpace, Mathf.LinearToGammaSpace と値を照合してみたら、「~Strict」の関数(厳密なコード)はほぼ同じで、「~Fast」(高速化近似式)の方は6割くらい一致するようだ(※ただし、誤差を甘めで、小数点3ケタくらいで比較した場合。べき乗を 2.233333f にすると 67%くらい)。しかし見た目では、静止画ならともかく、動いてる絵なら見分けが付かないくらいだ。

 また、これらの式をシェーダに使っている例もある。というより、近いものを Unity の PostProcessing で実装されているらしい。最後に抜粋してるので、興味があったら見てみると良い。



●シンプルな3次の高速近似式での変換

 また、下記のシェーダの計算を見ていると、2.2乗の近似式は単純に2乗(c * c)にされているが、もう1つ近似式があるね。コメントの ref の先に解説もあるが、なるほど計算負荷が低いらしい(基本的に平方根やべき乗などは、単純な掛け算や足し算より負荷が高いため)。

 もう1つの高速化近似式を C# で書いてみよう(そのまま)。

●シンプルな3次の高速近似式での Gamma → Linear 変換 (0~1f:正規化した値での計算)
using UnityEngine;

/// <summary>
/// ガンマ(sRGB)→リニア (0.0-1.0:正規化した値) 色空間変換 (高速化近似式: シンプルな3次)
/// (参考) http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
/// </summary>
/// <param name="gamma">0.0-1.0</param>
/// <returns>0.0-1.0</returns>
public static float ToLinearValueFastCubic(this float gamma)
{
return gamma * (gamma * (gamma * 0.305306011f + 0.682171111f) + 0.012522878f);
}

 最初の高速近似式(2.2乗)のコード内のコメントに「or 2.233333f」と書いてあるのは、こちらの資料にあったからだ。

 実際に試してみると、こちらも動いてる分には、ぱっと見た目わからない。平方根使うより計算負荷が軽いので、Unity も採用しているのだろう。これは助かる。

(参考資料) sRGB Approximations for HLSL



■シェーダでの利用

 以下のコードは実際に Unity の PostProcessing で使われているようだ。そのまま抜粋させて頂いた。

●シェーダ内 (.shader 等)での Gamma - Linear 相互変換 (0~1f:正規化した値での計算)
// sRGB transfer functions
// Fast path ref: http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
//
half SRGBToLinear(half c)
{
#if USE_VERY_FAST_SRGB
return c * c;
#elif USE_FAST_SRGB
return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);
#else
half linearRGBLo = c / 12.92;
half linearRGBHi = PositivePow((c + 0.055) / 1.055, 2.4);
half linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
return linearRGB;
#endif
}

half3 SRGBToLinear(half3 c)
{
#if USE_VERY_FAST_SRGB
return c * c;
#elif USE_FAST_SRGB
return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);
#else
half3 linearRGBLo = c / 12.92;
half3 linearRGBHi = PositivePow((c + 0.055) / 1.055, half3(2.4, 2.4, 2.4));
half3 linearRGB = (c <= 0.04045) ? linearRGBLo : linearRGBHi;
return linearRGB;
#endif
}

half4 SRGBToLinear(half4 c)
{
return half4(SRGBToLinear(c.rgb), c.a);
}

half LinearToSRGB(half c)
{
#if USE_VERY_FAST_SRGB
return sqrt(c);
#elif USE_FAST_SRGB
return max(1.055 * PositivePow(c, 0.416666667) - 0.055, 0.0);
#else
half sRGBLo = c * 12.92;
half sRGBHi = (PositivePow(c, 1.0 / 2.4) * 1.055) - 0.055;
half sRGB = (c <= 0.0031308) ? sRGBLo : sRGBHi;
return sRGB;
#endif
}

half3 LinearToSRGB(half3 c)
{
#if USE_VERY_FAST_SRGB
return sqrt(c);
#elif USE_FAST_SRGB
return max(1.055 * PositivePow(c, 0.416666667) - 0.055, 0.0);
#else
half3 sRGBLo = c * 12.92;
half3 sRGBHi = (PositivePow(c, half3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4)) * 1.055) - 0.055;
half3 sRGB = (c <= 0.0031308) ? sRGBLo : sRGBHi;
return sRGB;
#endif
}

half4 LinearToSRGB(half4 c)
{
return half4(LinearToSRGB(c.rgb), c.a);
}

 内容的には、厳密なコード高速化近似式 (2.2乗 や 1/2.2乗) に同じか近いね。プリプロセッサの「USE_VERY_FAST_SRGB」や「USE_FAST_SRGB」で実行速度を選択できるらしい。

 PositivePow は以下の参考資料を(LIGHT11)見て欲しい。正の値しか使わないのなら、ただの pow() でも可能のようだ。

(参考)
PostProcessing/PostProcessing/Shaders/Colors.hlsl (Unity の PostProcessing 内)
【Unity】シェーダにおける値のリニア <-> sRGB変換関数 (LIGHT11:PositivePow 掲載)

●PositivePow (負の値にしないべき乗) 抜粋
#define FLT_EPSILON     1.192092896e-07

// Using pow often result to a warning like this
// "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"
// PositivePow remove this warning when you know the value is positive and avoid inf/NAN.
float PositivePow(float base, float power)
{
return pow(max(abs(base), float(FLT_EPSILON)), power);
}

float2 PositivePow(float2 base, float2 power)
{
return pow(max(abs(base), float2(FLT_EPSILON, FLT_EPSILON)), power);
}

float3 PositivePow(float3 base, float3 power)
{
return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}

float4 PositivePow(float4 base, float4 power)
{
return pow(max(abs(base), float4(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}




 結局、どれを使うかはケースバイケースだと思うが、実装を知ってると色々応用が効くので知っておいて損は無い。例えば、ガンマ補正の値は 2.2乗 みたいになってるが(sRGBディスプレイの現在のデファクトスタンダードであり、過去には色々値が異なっていたらしい)、これを引数をして変更すると、見た目も変わる。これを応用してシェーダの方で Properties に入れておくと、インスペクタで変化の加減を調整できるので、とても便利だ。

 実際、VRM Live Viewer のプロジェクト内の素材を Linear 用に調整している最中だが、透過の無いテクスチャなどは、マテリアルの調整やいっそ PhotoShop でテクスチャの色調補正すれば、Gamma のときと同じ感じになるので事足りる。しかし、透過や反射するようなマテリアル(色や光の合成が行われるマテリアル)などは、どんなに調整しても Gamma のときと同じようにはならない(参考資料の「加算/合成が変わる」がわかりやすい)。そういう場合は、シェーダに変換式を入れないと、それっぽくはならないようだ(それでも完全には無理だが)。

(参考資料)
分かる!リニアワークフローのコンポジット






(関連記事)
【Unity】Standard Assets の Flare は Gamma 用だった?
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする
【Unity】【C#】Quality (グラフィック品質) を文字列で取得/設定する
【Unity】【C#】画面解像度とアクペクト比(整数)を求める
【HTML】HTMLカラー名・カラーコード表


関連記事

category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityリファレンス  C#ライブラリ  グラフィックス  算術関数  シェーダ 
tb: 0   cm: --

HTMLカラー名・カラーコード表  


HTMLカラー名・カラーコード表

カラー名名前タグコードタグカラーコード
White #ffffff
Snow #fffafa
GhostWhite #f8f8ff
WhiteSmoke #f5f5f5
FloralWhite #fffaf0
Linen #faf0e6
AntiqueWhite #faebd7
PapayaWhip #ffefd5
BlanchedAlmond #ffebcd
Bisque #ffe4c4
Moccasin #ffe4b5
NavajoWhite #ffdead
PeachPuff #ffdab9
MistyRose #ffe4e1
LavenderBlush #fff0f5
Seashell #fff5ee
OldLace #fdf5e6
Ivory #fffff0
Honeydew #f0fff0
MintCream #f5fffa
Azure #f0ffff
AliceBlue #f0f8ff
Lavender #e6e6fa
Black #000000
DarkSlateGray #2f4f4f
DarkSlateGrey #2f4f4f
DimGray #696969
DimGrey #696969
Gray #808080
Grey #808080
DarkGray #a9a9a9
DarkGrey #a9a9a9
Silver #c0c0c0
LightGray #d3d3d3
LightGrey #d3d3d3
Gainsboro #dcdcdc
LightSlateGray #778899
LightSlateGrey #778899
SlateGray #708090
SlateGrey #708090
LightSteelBlue #b0c4de
SteelBlue #4682b4
RoyalBlue #4169e1
MidnightBlue #191970
Navy #000080
DarkBlue #00008b
MediumBlue #0000cd
Blue #0000ff
DodgerBlue #1e90ff
CornflowerBlue #6495ed
DeepSkyBlue #00bfff
LightSkyBlue #87cefa
SkyBlue #87ceeb
LightBlue #add8e6
PowderBlue #b0e0e6
PaleTurquoise #afeeee
LightCyan #e0ffff
Cyan #00ffff
Aqua #00ffff
Turquoise #40e0d0
MediumTurquoise #48d1cc
DarkTurquoise #00ced1
LightSeaGreen #20b2aa
CadetBlue #5f9ea0
DarkCyan #008b8b
Teal #008080
SeaGreen #2e8b57
DarkOliveGreen #556b2f
DarkGreen #006400
Green #008000
ForestGreen #228b22
MediumSeaGreen #3cb371
DarkSeaGreen #8fbc8f
MediumAquamarine #66cdaa
Aquamarine #7fffd4
PaleGreen #98fb98
LightGreen #90ee90
SpringGreen #00ff7f
MediumSpringGreen #00fa9a
LawnGreen #7cfc00
Chartreuse #7fff00
GreenYellow #adff2f
Lime #00ff00
LimeGreen #32cd32
YellowGreen #9acd32
OliveDrab #6b8e23
Olive #808000
DarkKhaki #bdb76b
PaleGoldenrod #eee8aa
Cornsilk #fff8dc
Beige #f5f5dc
LightYellow #ffffe0
LightGoldenrodYellow #fafad2
LemonChiffon #fffacd
Wheat #f5deb3
Burlywood #deb887
Tan #d2b48c
Khaki #f0e68c
Yellow #ffff00
Gold #ffd700
Orange #ffa500
SandyBrown #f4a460
DarkOrange #ff8c00
Goldenrod #daa520
Peru #cd853f
DarkGoldenrod #b8860b
Chocolate #d2691e
Sienna #a0522d
SaddleBrown #8b4513
Maroon #800000
DarkRed #8b0000
Brown #a52a2a
Firebrick #b22222
IndianRed #cd5c5c
RosyBrown #bc8f8f
DarkSalmon #e9967a
LightCoral #f08080
Salmon #fa8072
LightSalmon #ffa07a
Coral #ff7f50
Tomato #ff6347
OrangeRed #ff4500
Red #ff0000
Crimson #dc143c
MediumVioletRed #c71585
DeepPink #ff1493
HotPink #ff69b4
PaleVioletRed #db7093
Pink #ffc0cb
LightPink #ffb6c1
Thistle #d8bfd8
Magenta #ff00ff
Fuchsia #ff00ff
Violet #ee82ee
Plum #dda0dd
Orchid #da70d6
MediumOrchid #ba55d3
DarkOrchid #9932cc
DarkViolet #9400d3
DarkMagenta #8b008b
Purple #800080
Indigo #4b0082
DarkSlateBlue #483d8b
BlueViolet #8a2be2
MediumPurple #9370db
SlateBlue #6a5acd
MediumSlateBlue #7b68ee


■色の表示について

「名前タグ」(左側)はカラー名で指定した場合の色、
(例) bgcolor="White"
「コードタグ」(右側)はカラーコードで指定した場合の色、
(例) bgcolor="#ffffff"
になります。

ブラウザが対応していればどちらも同じ色に表示されます。

■グレーの表記について

「Gray」と「Grey」どちらも同じものとして表記してあります。

■異名同色について

「Aqua」=「Cyan」
「Fuchsia」=「Magenta」
の2組です。カラーコードは同じになります。






(関連記事)
【Unity】色形式:Unity の Color と Android の ARGB(int32) の相互変換をする


関連記事

category: プログラミング

thread: ソフトウェア開発

janre: コンピュータ

tag: HTMLリファレンス  グラフィックス 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop