1 อธิบาย
ที่ขอบหุ่นยนต์ depth กระโดดจากใกล้ไปไกลทันที ถ้า defocus ภาพที่ merge แล้วครั้งเดียว สีของหุ่นยนต์จะเลอะเข้าไปใน background ที่เบลอ หรือหุ่นยนต์ที่เบลออยู่จะเหลือเส้นขอบคม ๆ
ตั้งโฟกัสเป็น “ที่หุ่น” แล้วเทียบผลของเรา (ซ้าย) กับ depth of field จริงของ Blender (ขวา) ลองทั้งสองวิธี (“defocus ครั้งเดียวหลัง merge” และ “defocus ทีละ layer แล้วค่อย merge”) แล้วอ่าน error ของแถบรอบขอบหุ่นของแต่ละวิธี depth pass ของหุ่นเป็นแบบ premultiplied เหมือนสีของมัน pixel ขอบที่ alpha 0.5 จึงมี depth ราว 4.8 m ขณะที่หุ่นอยู่ราว 9.0 m เป็นระยะที่ไม่มีอะไรอยู่จริง ส่วน view “depth (merge แล้ว)” (สว่าง = ใกล้) แสดงว่าขอบหลัง merge เป็นค่าผสมของ depth หุ่นกับพื้นข้างหลัง
CoC ∝ |z − focus| / z2 ลงมือลอง
โจทย์: ตั้งโฟกัสเป็น “ที่หุ่น” แล้วทำให้ error ของแถบรอบขอบหุ่นต่ำกว่าเป้าใน panel (กึ่งกลางระหว่างสองวิธี)
ดูขอบไหล่และหัวในภาพซ้ายเทียบขวา ถามตัวเองว่าภาพไหนมี background จริงอยู่หลังหุ่นยนต์ และ layer ไหนบ้างที่ต้องเบลอจริง ๆ
3 เจาะลึก
ทำไมขอบถึงพัง
ใน depth ขอบหุ่นยนต์คือจุดที่ค่ากระโดดจากใกล้ไปไกล พิกเซลขอบที่ anti-alias จะเฉลี่ย depth ใกล้กับไกลเข้าด้วยกัน ได้ความลึกที่ไม่มีวัตถุอะไรอยู่จริง
ภาพที่ merge แล้วยังมีปัญหาอีกชั้น ตรงหลังหุ่นยนต์ไม่มี background ให้เบลอ defocus จึงต้องใช้สีหุ่นยนต์แทน ใน figure ให้เทียบ readout สองบรรทัด วิธีครั้งเดียวค้างอยู่สูงกว่าแบบทีละ layer อย่างชัดเจน
| focus | อาการเมื่อ defocus ครั้งเดียว | สาเหตุ |
|---|---|---|
| ที่หุ่นยนต์ | halo สีหุ่นยนต์รอบตัวที่คม | background ที่เบลอดึงสีหุ่นยนต์เข้ามา |
| ไกล | เส้นขอบคมบนหุ่นยนต์ที่เบลอ | พิกเซลขอบถือ depth ของ background |
แยก layer แล้วค่อย merge
defocus plate ด้วย depth ของมันเอง และ defocus หุ่นยนต์ด้วย depth pass ของมันเอง แล้ว merge จากหลังมาหน้า plate มี background จริงอยู่หลังหุ่นยนต์ การเบลอจึงไม่ดึงสีหุ่นยนต์เข้ามา
layer ที่อยู่ใน focal plane ไม่ต้องผ่าน defocus เลย ปล่อยให้คมแล้ว merge ทับ ถ้ามีหลาย layer ให้ผูก focus และขนาดเบลอของทุก ZDefocus ไว้กับตัวควบคุมตัวเดียว
- 1plate + depth ของ set
- 2defocus plate
- 3หุ่นยนต์ + depth pass
- 4defocus เมื่อหลุด focus
- 5robot over plate
รู้ encoding ของ depth ก่อน
renderer อย่าง Cycles ให้ depth เป็นระยะห่างจากกล้องในหน่วยของฉาก ที่ว่างมีค่า inf หรือค่าสูงมาก ส่วน ScanlineRender และ DepthGenerator ของ Nuke ให้ 1/Z เป็นค่า default ใกล้ค่าสูง ไกลค่าเข้าหา 0
knob math ของ ZDefocus2 ต้องตรงกับ encoding ถ้าเลือกผิดจะไม่เบลอหรือเบลอเพี้ยน sample ค่าใกล้และไกลก่อนว่าค่าเพิ่มหรือลดตามระยะ ถ้าต้องการระยะจริงจาก 1/Z ใช้ Expression 1/z
| depth | ใกล้ / ไกล | math ใน ZDefocus2 |
|---|---|---|
| ระยะจากกล้อง (Cycles และ renderer ทั่วไป) | เล็ก / ใหญ่ | depth |
| 1/Z (ScanlineRender, DepthGenerator) | ใหญ่ / เข้าหา 0 | far=0 (ค่า default ของ Nuke) |
depth ต้องเต็มถึงขอบ
depth เป็นข้อมูล ไม่ใช่ภาพ ห้าม premult เพราะ depth จะลดลงเป็น 0 ที่ขอบและทำให้ defocus พัง และห้าม grade ให้ดูสวย เพราะ defocus ต้องการระยะจริง
ถ้าหุ่นยนต์เบลอแต่ยังมีเส้นขอบคม ให้ depth ฝั่งใกล้ชนะที่ขอบ เช่น EdgeExtend บน depth หรือ Dilate ขนาดติดลบ (min filter) ก่อน ZDefocus สำหรับ depth แบบระยะ ส่วน 1/Z ใช้ขนาดบวก fill_foreground ช่วยเดาส่วนที่ถูกเปิดเมื่อ foreground เบลอ แต่ไม่รู้ภาพจริงข้างหลัง จึงเป็นแค่การเดา
เปิด output เป็น focal plane setup ดูแถบ focus ก่อนตัดสินเรื่องเบลอทุกครั้ง
4 ในงานจริง
ทำใน Nuke
- Shuffle2 ย้าย depth ของแต่ละ layer เข้า depth.Z แล้ว sample ค่าใกล้และไกล
- EdgeExtend (channels Z) หรือ Dilate บน depth ให้ depth เต็มถึงขอบและฝั่งใกล้ชนะ แล้ว Copy กลับเข้า depth.Z ถ้าแยกทำ
- ZDefocus2 บน plate ตั้ง math ให้ตรง encoding (depth สำหรับระยะเป็นเมตร far=0 สำหรับ 1/Z) และดู focal plane setup
- ZDefocus2 บนหุ่นยนต์ที่ premult แล้ว เฉพาะเมื่อหลุด focus ผูก focus และขนาดกับตัวควบคุมหลัก
- Merge (over) หุ่นยนต์เป็น A ทับ plate ที่ defocus แล้วเป็น B จากหลังมาหน้า
พลาดบ่อย → แก้ยังไง
- ✗ defocus ภาพ comp ที่ merge แล้วด้วย depth เดียว✓ defocus แต่ละ layer แยกกัน แล้ว merge จากหลังมาหน้า
- ✗ ใช้ depth ที่ premult หรือ anti-alias ที่ขอบ✓ ทำ depth ให้เต็มถึงขอบด้วย EdgeExtend หรือ Dilate ให้ฝั่งใกล้ชนะ
- ✗ ตั้ง math ไม่ตรงกับ encoding ของ depth✓ sample ค่าใกล้และไกลก่อน แล้วเลือก depth หรือ far=0 ให้ตรง
- ✗ grade depth ให้ดูสวยใน viewer✓ ปล่อย depth เป็นค่าดิบ ถ้าอยากดูให้ปรับที่ viewer
- ✗ ส่ง layer ที่อยู่ใน focal plane ผ่าน defocus ด้วย✓ ปล่อยให้คม แล้ว merge ทับ layer ที่เบลอ
เช็กก่อนส่งช็อต
- math ของทุก ZDefocus ตรงกับ encoding ของ depth
- depth ไม่ premult ไม่ถูก grade และเต็มถึงขอบ rgb
- ดัน gain ที่ขอบแล้วไม่มี halo สีหุ่นยนต์ใน background ที่เบลอ
- หุ่นยนต์ที่เบลอไม่มีเส้นขอบคมเหลืออยู่
- focal plane setup อยู่บน subject ทุกเฟรม
- layer merge จากหลังมาหน้า และผูก focus กับตัวควบคุมเดียว
5 เช็กตัวเอง
focus อยู่ที่หุ่นยนต์ แต่ defocus ภาพที่ merge แล้วครั้งเดียว ทำไมจึงมีขอบสีส้มของหุ่นยนต์ฟุ้งรอบตัวที่คมอยู่
🔒 ตอบคำถามด้านบนก่อน แล้วการ์ดนี้จะเปิด
1. depth ของหุ่นยนต์จาก Cycles เป็นระยะจากกล้องเป็นเมตร ควรตั้ง math ของ ZDefocus2 อย่างไร
2. focus อยู่ไกล หุ่นยนต์เบลอแต่มีเส้นขอบคมวิ่งรอบตัว ควรแก้อย่างไร
ตัวเลขมาจากไหน: ภาพทั้งหมด render ด้วย Blender 5.2 Cycles จากฉากทะเลทรายและหุ่นยนต์ของเราเอง (tools/assets/passes_cg.py) แล้วคำนวณในเบราว์เซอร์ ภาพอ้างอิงคือ render ของ plate กับหุ่นที่เปิด depth of field ของกล้อง Blender ด้วยรูรับแสงกว้างกว่าเลนส์ 35 มม. จริงมาก (f/0.18) เพื่อให้เห็นเบลอที่ 640 px (aperture แบบสอนหลักการ) defocus ของเราเป็นการกระจายเป็นวงกลมขนาดตาม depth ต่อ pixel แบบสอนหลักการ ไม่ใช่ ZDefocus2 ของ Nuke ทั้งสองวิธีจึงไม่ถึงศูนย์ คะแนนคือ error เฉลี่ยในแถบรอบขอบหุ่น และเป้าวัดสดตอนโหลดภาพ