手で描くのめんどい
マツゲフレアを演出エフェクトとして再現すべく、光条の描き方を考えていたが、あっちこっちのサイトで光と回折の情報を漁るうち、結局はPCと先人の知恵に頼りまくる方針に行き着いた。
おおまかな作業工程は下記。
- C++で標準光源の単スリット回折をシミュレート、RGBデータへ変換する。
- 得られたデータから、Photoshopで基本素材となる虹色の干渉縞模様(32bit HDR画像)を生成する。
- 生成した素材を手作業で放射状などに並べ、フレアエフェクトを作成する。
この記事では 1. を、次の記事で 2. と 3. をまとめた。
単スリット回折の再現
まず単スリットでの光の回折を再現する。
数式の参考にしたのは、JSciencer様のこのページ。 展開を理解できる程の素養はないけど、結論の、スクリーン上の光強度比の部分はなんとか読めたので。
I(0)=1 としてコード化。
double getWaveAmp(double wavelength){ //at crrPixcel
double rad, n;
//単スリット式より
rad = std::atan2(
crrPixel * SCR_WIDTH_HALF / IMG_WIDTH_HALF, //スクリーン上の位置
SCR_DIST //スクリーンまでの距離
);
if(rad == 0){
//radian==0は特殊
n = 1.0;
}else{
//0以外
n = M_PI * SLIT_WIDTH * std::sin(rad) / wavelength;
n = std::pow( std::sin(n) / n, 2);
}
return n;
}
得られたグラフ2種。
波長3パターンを比較したものと、スリット幅3パターンを比較したもの。 縦軸は相対強度、横軸は将来的に画像中心からのピクセル位置となるもの。 出力したテキストを適当にExcelにぶっこんだらうまくグラフにしてくれた。 長波長ほど、またスリットが細いほど大きな回折縞となる。割と合ってるんじゃないかな。
sRGBへの変換
生成した回折縞データはRGBに変換しなければエフェクトとして使えない。 利用させていただいたのは下記にあるコード。 C界隈は探せば何でもあるなぁ。
fourmilab.ch::“Colour Rendering of Spectra”。
流れとしては、各波長の振幅を基本となるXYZ表色系に変換後、さらに各種表色系(今回はsRGB)に変換、というものらしい。 元のコードには sRGBへの変換データ(白色点と三原色点の値)が見当たらなかったので、Wikipedia等を参考に追加した。 参考ページによって細かい値がまちまちなのが謎だったけど脇に置く。
CIE標準光源と標準観測者
国際照明委員会CIEのサイトに、よく使うデータをまとめたxlsがあったのでいただく。
http://cie.co.at/technical-work/technical-resources の、”Selected Colorimetric Tables”。
左は、CIE標準光源D65。「普通っぽい色の光」について、波長5nm刻みで強度が示してある。大元の光源として使用できる。
右は、CIE1931測色標準観測者。やはり5nm刻みで「この波長はこの色に見える」という基準が示してある。これは上のXYZ表色系への変換にすでに使われてた。
処理全体像
やっとすべての情報が揃った。
スクリーン上の各点について、D65光源を単スリット回折させた強度を波長ごとに出し、XYZに変換して足しこみ、sRGB変換すれば、「虹色の縞模様」を表すデータが得られるはず。
なんか2千いくつとかマイナスとかあるけど気にしない。今回、色域外にプロットされた色の補正やガンマ補正をしなかった。 HDRだしノンリニアだし要らないかなあと。正解は知らない。
Excelさんで確認。それっぽい。
次項後編、画像化とそれっぽいエフェクト化。