X Motion · Orbit (オービット)
オービットは x-motion を拡張するものであり、置き換えるものではありません。コアメソッド(ブリーフ、テーゼ、ストーリーボード、批評)を実行し、アートディレクションとレシピにはこのファイルを使用してください。このスキルは、ヘッドレスChromium上のソフトウェアWebGLで renderFrame(t) から決定論的にレンダリングされる、8~12秒、1920×1080、30fpsの映像向けに書かれています。
ビジュアルテーゼ (Visual thesis)
宇宙は黒であり、光は出来事である。一つの光源(太陽)と、それが触れる物質:大気、海、雲、金属。すべての映像は、光が到来し、リムを横切り、あるいは解放されるその一瞬を中心に構築される。
スペクタクルよりも静かな確信。フレームの大部分は真っ黒で、被写体は大きくゆっくりとした質量(惑星、月、金庫の扉)と、細く明るいエッジである。もしフレームが壁紙やゲームのメニューのように見えるなら、写真のように見えるまで要素を削除せよ。
パレット (Palette)
線形HDRで作業し、最終的にトーンマッピングを行う。これらは、目が捉えるべき表示参照ターゲットである。
| 役割 | 16進数 | 使用法 |
|---|---|---|
| 真っ黒 (True black) | #000000 | ほとんどのフレームの60~80%。決してヘイズで持ち上げない。 |
| ボイドネイビー (Void navy) | #050b18 | 深宇宙のグラデーション。あらゆる光源から遠い。 |
| ディープネイビー (Deep navy) | #0b1a33 | 夜の海、影になった金属、「浮き上がり」後の暗い空。 |
| レイリーブルー (Rayleigh blue) | #2f6fd8 | 昼側の大気本体。 |
| 大気シアン (Atmospheric cyan) | #8fd3ff | フレネルリム、薄いリム線。 |
| サンライズゴールド (Sunrise gold) | #ffc46b | 太陽中心部の減衰、ターミネーター、雲頂上の最初の光。 |
| エンバーアンバー (Ember amber) | #ffa448 | 夜側の都市灯(ナトリウム)。 |
| コロナパール (Corona pearl) | #ece8de | コロナ、星、鐘のようなハイライト。 |
| チタニウム (Titanium) | #8a8f96 | ブラシ加工された金属の本体。 |
| ニッケル (Nickel) | #c3c6c8 | 金属のハイライト、ベベルの平面。 |
| シャンパン (Champagne) | #e9d4a6 | 金属上の暖色の鏡面エッジ。最大2ピクセルの線まで。 |
| オーロラグリーン (Aurora green) | #4ff0a0 | 酸素オーロラ。最大値の20%未満に抑える。 |
| H-アルファローズ (H-alpha rose) | #ff4a6e | 太陽プロミネンスと彩層のみ。 |
光と素材 (Light and material)
- 単一光源。 太陽が唯一の光源である。グロー、リム、グリントはその位置によって説明されなければならない。都市とオーロラのみが発光体であり、それらは夜側に存在する。
- 任意の恒星円盤に対するリム暗黒化 (Limb darkening):
I(mu) = 1 - 0.6*(1 - mu)、ここでmu = sqrt(1 - r*r)。金色から白への中心部は高温に見え、平坦な円盤はステッカーのように見える。 - 大気は散乱であり、線ではない。 照明されたリム上の青色(レイリー)、光がターミネーターをかすめる場所の金色、太陽が惑星の背後にあるときの前方散乱による明るさ。リムは薄く、惑星半径の約1.5%。
- 夜側 は黒ではない。冷たい月明かりによるフィルが海を濃い青色(決してオリーブ色ではない)に、陸地をより暗い中間色に、雲を銀白色に、円盤エッジにシアンのフレネルリムを、海岸線に沿った琥珀色の都市クラスターを、そしてリムに淡い緑色の大気光(エアグロー)の線を保つ。暖色の金色は、太陽が実際に到達する場所にのみ現れる。
- 海面のグリント (Ocean glint): 太陽が反射する場所にできる柔らかな鏡面ローブ。リムに向かって伸びる。海上のみ。
- 金属: ブラシ加工されたチタンは異方性である。ハイライトはブラシ方向に伸び、ベベルは薄いシャンパン色のエッジを捉え、継ぎ目にはオクルージョンが生じる。クロームミラー、バンプマップノイズは使用しない。
- レンズ: 1本のアナモルフィックストリーク(水平、薄い、シアンがかった色)、フレーム中心を通る線に沿った2~4個のかすかなゴースト。ゴーストの不透明度は4%未満。ACESスタイルのカーブでトーンマッピングする。ハイライトを数ピクセル以上フラットな白にクリップしない。
構図 (Composition)
- 水平線は三分割線上に配置し、決して中央を通らない。惑星のリムは大きな弧を描く(半径はフレーム高の1.5~4倍)。小さな地球全体はおもちゃのように見える。
- 光のイベント(太陽の頂点、ダイヤモンドリング、最初の光)は三分割線上に配置する。ショットが対称性(金庫の扉、日食)に関するものでない限り、中央は避ける。
- 星はまばらに(数百個可視)、サイズは1~2ピクセルでソフトな減衰を持ち、温度によってわずかに暖色または寒色にする。フレームが暗くなると現れ、明るくなると露出に応じてフェードアウトする。
- テキスト、ロゴ、HUD、星雲の壁紙、レンズの汚れは使用しない。一度に一つの被写体。
モーション語彙とタイミング (Motion vocabulary and timing)
動詞:密閉する、ラッチを外す、分かれる、落ちる、昇る、頂点に達する、滑空する、飲み込む、展開する、解放する、浮かび上がる。カメラは決して揺れず、めったにカットしない。質量はゆっくりと動き、光は速く動く。
| ビート | 典型的な長さ | カーブ |
|---|---|---|
| 密閉された、または暗いフレームで静止 | 1.0~1.5秒 | 静的、光のスイープのみ |
| 機械的なラッチ解除 | 0.10~0.20秒 | 高速イーズアウト、わずかな落ち着き |
| 扉が開く / 落下 | 0.8~1.4秒 | スロースタート、指数関数的加速 |
| ワープ(ストリーク) | 1.2~2.0秒 | 早期にピークに達し、滑らかに減衰して静止。まばらで、フレームはほとんど黒のまま |
| 惑星の上昇 / 軌道滑空 | 3~6秒 | 長いイーズインアウト、決して線形ではない |
| 太陽の頂点またはダイヤモンドリング | フルフレアまで0.3~0.6秒 | 鋭い立ち上がり、ゆっくりとしたブルーム |
| 解決と静止 | ≥ 1.5秒 | ほとんど静止。コードを響かせよ |
モーションは t から閉形式で計算される。位置はオーサリングされた速度曲線の積分であり、フレームごとに蓄積されることはない。ワープ移動は s(t) = integral of v であり、ストリークの長さは s(t) - s(t - shutter) である。ストリークは少数(レイヤーあたり数十、数百ではない)に保ち、長くソフトにし、遠いレイヤーは近いものより暗く細くする。密集した均一なバーストは、ストックのハイパースペースのように見える。
サウンドパレットとミックス (Sound palette and mix)
- サブ (Sub) (30~60 Hzのサイン波でゆっくりとしたうねり) が質量を伝える。マスターを約25 Hzでハイパスフィルターする(レンダリング後、JSで。オーディオマスターレシピ参照)。
- 金属: モーダルシンセシス。5~10 msのバンドパスされたノイズクリックと、4~6の非調和サイン部分音(例:f0の1.00、2.32、3.86、5.40倍)、減衰時間0.1~0.8秒。
- 風と移動: 移動するバンドパスを通したシード付きノイズ。画像にパンニングを合わせる。ストックのウィッシュ音は使用しない。
- ハーモニー: テンションのあるサスペンドパッド(sus2、sus4)。光のイベントでメジャーadd9に解決する。パッドは、ノートあたり3つのデチューンされた鋸波を600~1800 Hzのローパスフィルターに通したもの。
- 鐘: 加算的な非調和部分音(1、2.0、2.76、4.07、5.4)で、アタックは3~8 ms、減衰は部分音のインデックスとともに短くなる。
- リバーブ: 1つの
ConvolverNodeとシード付きステレオインパルス(2.5~4.5秒の指数減衰、20 msのプリディレイ、より暗いテール)。 - 沈黙は合図である。 画像が暗くなったら音を薄くせよ。光のイベントに最初の大きな瞬間を任せよ。
- ターゲット: インテグレーテッド -18 LUFS、トゥルーピーク ≤ -1.5 dBFS、テールは終了0.3秒前に完全に減衰。コードで測定し、ノーマライズし、リミッターをかける。
テクニックレシピ (Technique recipes)
パイプライン。 ソフトウェアWebGLは遅いため、作業を分割する。ハーフ解像度パスで滑らかなHDRシーン(惑星、大気、コロナ)を RGBA16F テクスチャにレンダリングし、フル解像度パスでそれをアップサンプリングし、シャープな詳細(星、都市灯、フレア、金属エッジ)を追加し、トーンマッピングとディザリングを行う。フレームあたりの秒数を測定し、1080pで1.5秒未満に抑える。
レイ・球体 (Ray–sphere)。 表面のマーチングは行わず、解析的に解く:
vec2 sphere(vec3 ro, vec3 rd, float R) { // t near, t far; t < 0 はミス
float b = dot(ro, rd), c = dot(ro, ro) - R*R, h = b*b - c;
if (h < 0.0) return vec2(-1.0);
h = sqrt(h); return vec2(-b - h, -b + h);
}
大気 (Atmosphere)。 シェル内の視線に沿った単一散乱(8~12ステップ)。光路の光学的深度は3~4ステップで近似。レイリー係数 vec3(5.8, 13.5, 33.1)(惑星半径に合わせてスケーリング)、ミー散乱はヘニー・グリーンスタイン位相関数 g = 0.76。光線がシェルに入らないピクセルはスキップする。
都市灯 (City lights)。 クラスターハッシュノイズ。陸地と夜によってマスクされる:
float night = smoothstep(0.05, -0.15, dot(n, sunDir));
float c = pow(max(fbm3(p*40.0) - 0.45, 0.0)*3.0, 2.0) * land * night;
col += c * vec3(1.0, 0.62, 0.28) * 6.0; // 琥珀色、HDR
星、バンド幅制限 (Stars, band-limited)。 グリッドセルあたり1つの星。ジッターを加え、少なくとも0.8ピクセルのシグマを持つガウス分布で描画する。これにより、モーションが決してストロボしない:
vec2 cell = floor(px / 24.0), f = px - (cell + hash22(cell)) * 24.0;
float star = exp(-dot(f, f) / 1.6) * pow(hash12(cell + 7.1), 18.0) * 3.0;
太陽の頂点フレア (Sun crest flare)。 すべての要素は、太陽のスクリーン位置 s と可視割合 v(JSで計算)を中心に解析的に計算される:
vec2 d = uv - s;
float core = exp(-dot(d, d) * 9000.0), halo = 0.04 / (1.0 + dot(d, d) * 400.0);
float streak = exp(-abs(d.y) * 900.0) * exp(-abs(d.x) * 2.2);
vec3 flare = v * (core * vec3(1.0, .9, .75) * 40.0 + halo * gold + streak * cyan * 2.0);
for (int i = 0; i < 3; i++) { vec2 g = -s * kGhost[i]; /* g位置にソフトディスク、2~4% */ }
ブラシ加工チタン (Brushed titanium)。 ブラシ方向に沿った接線による異方性ハイライト。加えて、かすかなバンド幅制限ストリーク(波長 ≥ 3 ピクセル):
float TH = dot(T, H);
float aniso = pow(sqrt(max(1.0 - TH*TH, 0.0)), 60.0);
float grain = 0.92 + 0.08 * noise(vec2(r * 300.0, angle * 3.0));
vec3 metal = base * (0.25 + 0.75 * diffuse) * grain + champagne * aniso;
日食 (Eclipse)。 月は太陽よりわずかに大きい(1.04~1.08倍)。月のリムにわずかなノイズを加え、ベイリービーズとダイヤモンドリングが接触付近で自然に現れるようにする。コロナ:明るさ pow(r, -3) に、ノイズからのストリーマー(角度、log r)と、高い角度周波数、低い半径方向周波数のノイズからの微細なフィラメントを組み合わせる。
リムプロファイルを、整数周波数のサイン波とラップされたガウス型ノッチの和として一度書き、それをJSとGLSL文字列の両方として出力する。JSは次に、フレームごとに可視光球を積分できる(太陽中心の光線あたり1回の二分法、約700光線)。これにより、可視割合、グレアのためのビーズ重心、そしてスコアのための正確な接触時刻が得られる。ビーズグレアには割合の対数マッピングが必要である(例: log(1 + f*1e6) / log(1 + 1e6))。粗いミップから描画された広いグレアは、HDRソース上で階段状のアーティファクトを示すため、各レベルをハーフテクセルオフセットでの4つのバイリニアタップでぼかす。
オーディオマスター (決定論的) (Audio master (deterministic))。 startRendering() の後、JSでインテグレーテッドLUFS (BS.1770 K-ウェイティングとゲーティング) を測定し、-18にスケーリングし、-1.5 dBFSで4倍オーバーサンプリングされたピークにルックアヘッドピークリミッターを適用する。すべてのノイズバッファとインパルスを mulberry32 でシードする。
ヘッドレスChromiumでは、これらはビット単位の再現テストに失敗する:マスター BiquadFilterNode または DynamicsCompressorNode を通過するステレオ信号、および3つ以上の入力を持つノード。加算順序が1 ULP異なるためである。マスターバスをノードフリーに保つ(ゲインからデスティネーションへ)。ハイパスフィルターとバスコンプレッションは、レンダリング後にJSで実行する。リバーブのハイパスフィルターをそのインパルスに焼き付ける。すべてのファンイン(多入力合成)を2入力ゲインでチェーンする。a + b は正確で可換であるため。
function mulberry32(a){return()=>{a|=0;a=a+0x6D2B79F5|0;let t=Math.imul(a^a>>>15,1|a);
t=t+Math.imul(t^t>>>7,61|t)^t;return((t^t>>>14)>>>0)/4294967296;};}
決定論的チェックリスト (Deterministic checklist)
renderFrame(t)はすべてのユニフォームをtのみから設定する。レンダーモードではDate、performance.now、Math.random、フレームごとの蓄積を使用しない。- シード付きハッシュとPRNGのみを使用。画像と音声が一致しなければならない場合は同じシードを使用する。
- 後方へのシークは同一のピクセルを再現する。後のフレームの後に t = 0 をテストせよ。
preserveDrawingBuffer: true、antialias: false。renderFrameの終わりにgl.finish()を呼び出す。- プレビューモードは
requestAnimationFrameでループする。?render=1はそれ自体では何も描画しない。 renderAudioは呼び出しごとに同じバッファを返す。2回のレンダリング間でサンプルごとに比較すること。ラウドネスとトゥルーピークは測定され、推測ではない。- 光のイベント、その1フレーム前、および最後のフレームで静止画を検査する。フレームごとのタイミングを確認する。
避けるべきこと (Avoid)
- 漫画のような輪郭線、惑星の周りの発光する輪郭、飽和した紫色の星雲、六角形のリングがあるレンズフレアのプリセット。
- 回転する地球儀、高速なカメラ移動、シェイク、物理的な原因のないスピードライン。
- ハイライトをフラットな白にクリップすること、持ち上げられた黒、バンディング(出力前にサブLSBのディザを追加すること)。
- フレーム全体のグレインや1ピクセルのスパークル。これらはストロボし、H.264を肥大化させる。
- すべての動きに対する効果音、安っぽいウィッシュ音、行き止まりのライザー、バッファエッジでのクリック、映像の終わりで途切れるリバーブテール。
- ブリーフで要求されていない限り、テキスト、ロゴ、インターフェースクローム。