🎨

構造・熱・流体解析などのコンター図のカラーバーの色をShaderでif文を使わずに計算

2023/06/02に公開

コンター図とは

構造・熱・流体解析などのCAEでは解析結果を色で確認することが多いです。

例えば
 ・構造解析なら変位量、応力
 ・熱解析なら温度
 ・流体解析なら圧力
などの物理量を色で確認します。

この「空間上の値を色で表現したもの」をコンター図というらしいです。また、どのくらいの値が何色なのかを示すカラーバーが必ずあり、構造解析では値が大きくなるにつれて青→赤に色が変化するカラースケールを使うことが多いです。(下図:FreeCADによる構造解析例)

コンター図の色計算

入力値0.0→1.0に対して出力色が青→赤に変化するプログラムをif文を使わずに書きます。

●区切りのよい場所を抽出して表にするとこんな感じ

●グラフにするとこんな感じ

●フラグメントシェーダーはこんな感じ

// 入力値0.0~1.0
float Input = 0.0;

// 出力色宣言 & 初期化
half4 Col = 1.0;

// 赤色成分計算
Col.r   = clamp(( 4.0 * Input) - 2.0, 0.0, 1.0); // y=4x-2を0.0~1.0にクランプ

// 緑色成分計算
half G1 = clamp(( 4.0 * Input)      , 0.0, 1.0); // y=4x   を0.0~1.0にクランプ
half G2 = clamp((-4.0 * Input) + 4.0, 0.0, 1.0); // y=-4x+4を0.0~1.0にクランプ
Col.g   = lerp(G1, G2, step(0.5, Input));        // Inputが0.5未満ならG1、以上ならG2にする

// 青色成分計算
Col.b   = clamp((-4.0 * Input) + 2.0, 0.0, 1.0); // y=-4x+2を0.0~1.0にクランプ

// 出力色の色空間をsRGB色空間からリニア色空間に近似式で変換
Col.rgb = pow(Col.rgb, 2.2);

// 色の出力
return Col;

色空間の変換については以下の記事をご参照ください
https://zenn.dev/dimebag29/articles/23641e7d8e0805

コンター図の色計算が必要になった場面

まだ未完成ですが、
2023年3月におふざけでFreeCADの解析結果をVRChat内で展示するワールドを作りました。
https://twitter.com/Hyper_Mesh/status/1719166548223680956

このワールドで展示している解析モデルの各頂点には、
頂点カラーのrgbに変位量、aにミーゼス応力値が格納してあって、
この頂点カラーの情報をもとにShaderでモデルを変形、応力値を色で表示しています。

応力値の色計算にあたり、
最初は下図のようにHSV・HSBの色相の値を応力値に合わせて増減させれば簡単だと思ってましたが、Shaderでは結局最終的にRGBで色を指定する必要があり、さらにHSV・HSBからRGBに変換する関数も見つけられませんでした。

ネットを検索するとHSV・HSBからRGBに変換するShaderを公開してくださっている方は何人もいらっしゃるのですが、計算過程でif文がいくつも使われており、「Shaderでif文使うな」という噂をよく耳にしている自分としてはそれを使うのが怖くて結局自分で作ることにしました。

Discussion