LEVEL 3 · ระดับสูง
กลไกภายใน: เครื่องถ่ายทีละเฟรม
บทนี้เปิดฝากล่องเครื่องเรนเดอร์ แล้วปริศนาทุกข้อที่เล่มนี้ปลูกไว้จะถูกไขพร้อมกันด้วยเหตุผลเดียว
11.1 ไปป์ไลน์จริงจาก log
เรนเดอร์การ์ด 10 วินาทีหนึ่งรอบ log เล่าไปป์ไลน์ครบ (ตัดมาเฉพาะสาระ):
phase: capture totalFrames: 300 workerCount: 4 captureMode: beginframe
phase: encode (FFmpeg เย็บเฟรมเป็นวิดีโอ)
phase: assemble hasAudio: true (ผสมเสียง ปิดไฟล์)จุดที่ควรหยุดอ่านคือ workerCount: 4 — เครื่องเปิดเบราว์เซอร์หลายตัวแบ่งกันถามคนละช่วงเฟรมพร้อมกัน เฟรม 200 อาจถูกถ่ายก่อนเฟรม 50 ไม่มีการ "เล่นจากต้นจนจบ" อยู่ในระบบเลยแม้แต่ขั้นตอนเดียว
workerCount: 4 — สี่เบราว์เซอร์แบ่งกันถามคนละช่วงเฟรมพร้อมกัน เฟรม 200 จึงอาจถูกถ่ายก่อนเฟรม 50 · จากนั้นสามเฟสตามลำดับ capture → encode → assemble (ผสมเสียง) · ไม่มี “เล่นจากต้นจนจบ” อยู่ในระบบแม้แต่ขั้นตอนเดียว — รากของกฎ determinism ทุกข้อ11.2 ปริศนาทั้งเล่ม ไขด้วยประโยคเดียว
ทุกกฎของ HyperFrames คือผลของข้อเท็จจริงที่ว่า เฟรมถูกถามไม่เรียงลำดับและถามซ้ำได้:
- ห้าม
Math.random()/ นาฬิกาจริง / fetch ตอนเรนเดอร์ — ค่าพวกนี้ตอบไม่เหมือนเดิมต่อคำถามเดิม (ปลูกไว้บทที่ 2) - ห้ามเพจเล่นสื่อเอง — เวลาไหลจริงผูกคำตอบกับ "ตอนไหนที่ถาม" (ไขแล้วบทที่ 7)
- ห้าม animation วนไม่รู้จบ (
repeat: -1) — ตำแหน่งในลูปนิยามจากเวลาไม่ได้ถ้าไม่รู้จำนวนรอบ ใช้จำนวนจำกัดที่คำนวณจากความยาวจริง (ปลูกไว้บทที่ 2) - timeline ต้อง paused และ fromTo ชนะ to — การ "จำสภาพตอนเริ่ม" ขึ้นกับลำดับการถาม (ไขแล้วบทที่ 5)
- แม้แต่ hover / scroll ก็ต้องห้าม — เครื่องเรนเดอร์ไม่มีมือ ไม่มี input event ใด ๆ
11.3 พิสูจน์เชิงประจักษ์ — hash ไม่โกหก
ผมเติม Math.random() หนึ่งบรรทัดให้เส้นใต้เอียงแบบสุ่ม แล้วถ่ายเฟรมที่ t=5 สองรอบ จากนั้นถอดออกแล้วถ่ายซ้ำอีกสองรอบ เทียบ hash ระดับพิกเซล:
มี Math.random run1: 98820fd7... run2: 5490ad2c... ← คนละภาพ
โค้ดสะอาด run1: cdaa3183... run2: cdaa3183... ← เหมือนกันทุก byteโค้ดสะอาดตอบ f(t) เดิมเป๊ะทุกครั้งจริง ๆ ไม่ใช่วาทกรรม — และหนึ่งบรรทัดสุ่มทำลายมันทันที ลองเองได้ในหนึ่งนาที: snapshot --at 5 สองรอบแล้วเทียบไฟล์
กฎทุกข้อที่ดู "จุกจิก" ของ framework นี้ คือราคาของสัญญาเดียว: ถามเฟรมไหน เมื่อไหร่ กี่รอบ ก็ได้ภาพเดิม