3D 縮放解說器
這是一種比任何圖表都更能解釋尺度的格式:從每個人都知道的物體開始,不間斷地飛入其中,在螢幕上保留一個數字告訴觀眾他們已經走了多遠,最後以一個他們意想不到的事實作結。此技能的參考結果是「沒有東西是真的鋒利」:一把刮鬍刀片、26次對半、一個鐵原子,以及其邊緣仍然約有300個原子寬的事實。
assets/template/ 是這個已完成的專案。從它而不是從空白檔案開始:困難的部分(在沒有精度損失的情況下縮放八個數量級、隨尺度變化的細節、景深、確定性渲染器)已經在那裡解決,並且經過了好幾輪才搞定。
公式
保留全部五個要素。每個要素都在發揮作用。
- 一個連續鏡頭。 重點在於觀眾永遠不會迷失位置。一個剪輯會重置他們對尺度的感知。
- 一個即時測量。 一條固定在主題上的細條、一個每幀都變化的數字、一個對半(或加倍)的計數,以及兩三個描述當前視野的詞。這條細條是觀眾唯一需要閱讀的東西,所以它必須誠實:它在場景中的長度確實就是顯示的數字。
- 主題在每個尺度都會改變特性。 拋光變成研磨痕跡,再變成碎屑,然後變成晶粒,再變成圓角,最後變成原子。如果表面在三秒鐘內看起來都一樣,那麼縮放就會被解讀為什麼都沒發生。
- 對比物體。 當縮放經過每個尺寸時,一個該尺寸的熟悉物體會放在主題旁邊,並標示其名稱和尺寸:鹽粒、頭髮、紅血球、細菌、病毒、電晶體、抗體、DNA。它們把一個抽象的數字變成「比病毒還小」。
- 一個亮點。 快速拉回你開始的地方,並展示這次旅程唯一的那個數字。
工作流程
1. 建模前先研究
影片只有在真實的情況下才值得製作。查閱真實尺寸(網路搜尋,盡量使用主要來源),並為主題和每個對比物體寫下:尺寸、來源,以及你正在簡化的任何內容。幾何形狀是根據這些數字建立的,所以畫面不能偏離事實。最後向使用者報告來源和簡化內容;他們會提出疑問。
選擇6到9個對比物體,每個大約比前一個小至少3倍。比這更近的話,它們的標籤會碰撞;比大約30倍更遠的話,螢幕會空好幾秒。
2. 在有用時顯示計劃
如果使用者要求先看計劃,或者簡報留下了真正的選擇空間(旁白或無聲、語言、亮點是什麼),則提供一個簡短的表格:時間、尺度、視野中的內容、對比物體。否則就直接進行;沒有人要求的計劃只會延遲第一次渲染。
3. 設定專案
cp -r <skill>/assets/template <project>/ && cd <project> && npm install
node render.mjs --stills 1,10,20,30,40
第二個指令應該會印出GPU名稱並寫出五張JPEG到 out/。如果它報告 SwiftShader 或 llvmpipe,則渲染是在CPU上進行的,將會耗費數小時:在繼續之前先修好GPU旗標(參見 references/pitfalls.md)。
4. 調整場景
main.js 是一個檔案,分成幾個區塊。在進行任何結構性更改之前,請先閱讀 references/techniques.md;它解釋了每個部分為什麼這樣建構。對於一個新主題來說,通常需要更改的部分是:
main.js 中的區塊 | 要替換的內容 |
|---|---|
| constants | 以公尺為單位的物理數據、起始尺寸 L0、對半次數 HMAX、時間軸 |
| subject surface | 橫截面 prof()、輪廓裁剪、表面特徵表格 FEATS(波長、類型、強度) |
| finest scale | 原子晶格(或最後階段由什麼組成) |
| things for scale | addObj(name, sizeText, sizeInMetres, geometry, material, placement) 列表 |
| overlay | LABELS(每個縮放等級視野中的內容)、最終說明文字 |
| camera keys | K_AZ、K_EL、K_TY、K_D、K_AP 作為縮放等級的函數 |
對於形狀不同的主題(晶片、葉子、一張紙),保留機制並替換輪廓和特徵。對於向外縮放,則反向執行相同的時間軸並說「加倍」。
5. 在渲染影片之前檢查靜態圖
渲染分佈在時間軸上的8到10張靜態圖,用 ffmpeg 將它們拼貼成接觸表並進行檢查。然後修正你看到的問題並重複。這個循環是品質的來源;參考影片第一版中的每個問題在靜態圖中都可見,而在程式碼中卻都不可見。特別檢查:
- 曝光。 第一遍幾乎總是過曝。金屬應該大多是暗的,帶有清晰的亮部。
- 任何被畫面邊緣切掉的東西,尤其是靠近頂部的對比物體。
- 標籤位於明亮區域上方或彼此重疊。 將測量標籤保持在空的黑區。
- 每個階段是否看起來像其標籤所說的那樣。 如果標籤說「晶粒」而畫面是條紋,那麼其中一個是錯的。
- 第一幀和最後一幀,因為它們是縮圖和重點。
ffmpeg -y -i a.jpg -i b.jpg -i c.jpg -i d.jpg -filter_complex "[0][1]hstack[t];[2][3]hstack[u];[t][u]vstack,scale=1920:-1" sheet.jpg
6. 渲染並驗證結果
node render.mjs --full --o video.mp4 # 如果有旁白則加上 --audio vo.wav
在背景執行它;一個45秒的1080p影片在獨立GPU上需要幾分鐘。然後檢查檔案本身,而不是你之前製作的靜態圖:探查持續時間和大小,提取一個概覽網格,並從繁忙的片段中提取六個連續幀以檢查閃爍。精細的程序化細節壓縮效果很差,所以預期檔案會很大,並在需要時製作一個較小的副本:
ffmpeg -i video.mp4 -vf "fps=1/3,scale=640:-1,tile=4x4" -frames:v 1 overview.jpg
ffmpeg -ss 13 -i video.mp4 -vf "crop=960:540:480:270,tile=3x2" -frames:v 1 consecutive.jpg
ffmpeg -i video.mp4 -vf scale=1280:720 -c:v libx264 -preset slow -crf 25 -maxrate 4200k -bufsize 8400k small.mp4
清楚說明你驗證了什麼以及沒有驗證什麼。幀網格證明畫面是正確的;它們不能證明運動感覺是對的,所以應該說使用者應該觀看它。
預設值
- 無聲。 除非要求,否則沒有音樂、沒有音效、沒有旁白。這個格式本身就足夠了,而且它的參考來源也沒有旁白。
- 文字僅包含數據和名稱。 測量值、對半計數、視野中的內容、對比物體的名稱和尺寸、一個最終數字。如果添加了旁白,就刪除語音已經說過的每個標籤,因為閱讀和聆聽相同的詞語會分散注意力。
- 1920x1080,30 fps,40到50秒,以1.5倍渲染後再降頻。對於垂直影片,更改
W和H並重新檢查每個靜態圖;構圖不會自動轉移。 - 標籤使用使用者觀眾的語言,這不一定是他們聊天時使用的語言。如果不清楚,請詢問。
添加旁白
僅在被要求時才添加。將劇本寫成簡短的台詞,每句屬於一個階段,產生或接收音訊,取得單詞時間戳(faster-whisper 效果很好),然後根據音訊驅動縮放:縮放等級成為一個關鍵幀化的時間函數,在解釋一個階段時保持不變,並在台詞之間移動。將音訊傳遞給 render.mjs --audio。在每個停頓期間讓一些小事情發生(光線掃過、物體到達、原子振動),否則暫停的縮放看起來就像凍結了一樣。
參考檔案
references/techniques.md- 模板如何運作及其原因:圍繞焦點縮放、尺度視窗化的程序化細節、球體假象、景深、錨定在物理空間中的物體、確定性渲染器。在結構性更改之前閱讀。references/pitfalls.md- 已經遇到過的失敗及其修復方法。當渲染看起來不對或工具行為異常時閱讀。MASTER_PROMPT.md- 用於開始新影片的填空提示,以及符合這個公式的主題點子。