ทดลองทำ blur ปลอมด้วย pixel interpolation
ในเกมผมพอดีว่าจะใช้ blur มาช่วยเติมในส่วนที่ iPad จอทรงสูงกว่า iPhone เพราะอยากให้นักวาดรูปวาดอิงขนาด iPhone อย่างเดียวก็พอ
ซึ่งถ้าเราทำการ post-process ภาพให้กลายเป็น blur ใน runtime นี่พบว่ามัน lag มากครับ พยายาม optimize ให้ post-process แค่ frame เดียวแล้วเก็บภาพนั้นไว้ใช้ ก็ยังกระตุกอยู่ดีตอน frame เดียวนั้นแหละ
Blur ที่เห็นเป็นเอาภาพชัด (ที่ render ใส่ RenderTexture ไว้) ขนาดย่อครึ่งนึงจากขนาดจอเหลือ 568x320 เพื่อประหยัด RAM หน่อย แล้วมาผ่าน post-processing stack ของ Unity ที่เขาแจกไว้ใน Asset Store
เป็นระบบใหม่ แทนได้ทุก effects แต่จะเหมาะกับเกมคอมมากกว่า มือถือไม่น่าใส่เอฟเฟคอะไรไว้ที่กล้อง
Unity-Technologies/PostProcessing
PostProcessing — Post Processing Stackgithub.com
เอามาใช้แล้วจะสามารถเลือก effects ได้มากมายแบบนี้ ซึ่งในภาพที่เห็นลองเอา Depth Of Field กับ Color Grading มาทำให้มืดๆลง
คาดว่า depth of field มันคงมี algorithm ไฮโซอะไรซักอย่างอยู่ ถ้า blur ที่ simple สุดๆก็คงเป็น box blur ที่แบบเอา kernel (matrix ของตัวเลขกล่องนึง ที่มีสมาชิก n ตัว เลขทุกตัวจะมีค่า 1/n เพราะจะได้รวมกันกลับมาได้ 1) ขนาดเท่าที่ต้องการให้ฟุ้งมาสไลด์ผ่านทุก pixel ให้มันคิดค่าสีใหม่ (สไลด์แล้วคิดเลขคล้ายๆ fourier transform อะครับ) ไม่รู้ถ้าวิธี box blur นั้นมันจะเร็วขึ้นมั้ย แต่พอดีไม่ได้ลอง
มี solution ที่คิดออกคือ ทำเบลอไว้ก่อนแล้วเซฟเก็บไว้เป็นภาพรวมเข้าไปใน asset แต่แบบนั้นนอกจากจะกินที่เกมแล้วถ้าเปลี่ยนอะไรคงต้องมายุ่งยากอัพเดทแก้ทีหลัง
อีก solution นึงก็คือ ใช้ loading screen ทำการ blur คิดเก็บไว้ทั้งหมดก่อน แต่กลัวว่าเกมใหญ่ขึ้นแล้วพื้นที่ texture จะกิน RAM เยอะไปหน่อย อยากคำนวณ blur สดแล้วทิ้งรัวๆได้มากกว่า
ก็เลยได้อีกไอเดียนึงคือใช้สมบัติ resampling ของ texture ให้เป็นประโยชน์ ก็คือทำภาพเล็กมากๆมาแล้วเอามาขยายให้แตกระเบิด (ขยายตอนแสดงผล ไม่ใช่ขยายไฟล์ภาพจริงๆ) ถ้าภาพขนาดเล็กไม่มากอาจจะน่าเกลียด แต่ถ้าเล็กสุดๆอาจจะกลายเป็น blur ที่สวยงามได้
เพราะงั้นเรามาทดสอบสมมติฐานนั้นดูว่าจริงมั้ย
Prototype ใน Photoshop กันดูดีกว่า
จะบอกว่าเป็นสิ่งที่ได้จากการเรียน ป.โทก็ว่าได้ครับ คือจะทำอะไรก่อนอื่นหัวจะคิดหาวิธีลองที่เร็ว and dirty ที่สุดดูก่อน 555
ก่อนอื่นก็ลองย่อภาพให้เล็กก่อน
แล้วขยายกลับมา
ทดสอบดูแล้วขยายกลับมาก็ดู blur ใช้ได้เลย
อันนี้เป็นแบบ bilinear ส่วนตัวไม่ค่อยชอบเท่าไหร่เพราะเห็นเป็นดาวแฉกๆ แต่อาจจะเป็นเพราะภาพยังไม่เล็กพอก็ได้ จะ blur ก็ไม่ใช่ จะชัดก็ไม่ใช่
อันนี้ลองเปลี่ยนเป็น bicubic รู้สึกชอบ algorithm นี้เพราะเห็นเป็นกลมๆนัวๆ แต่ใน Unity มันไม่มีนะครับ ก็หวังว่า bilinear ของ Unity จะออกมาดูดี
ผลลัพธ์ใน Unity
จะเห็นว่าครั้งนี้เทียบกับภาพบนสุดของ blog post นี้ ภาพต้นแบบเล็กมากเหลือแค่ 23 x 13 เอง ซึ่งเซ็ต filter mode เป็น Bilinear ส่วน Trilinear ลองแล้วผลเหมือนกัน (สุดท้ายใช้ Unity มาหลายปีก็ไม่รู้ว่าต่างกันตรงไหน) แค่อย่าเป็น point mode ก็พอ (แต่ถ้าชอบเป็น pixelated ก็ลองก็ได้ครับ แต่มันก็จะไม่ blur)
ผลออกมาใช้ได้อย่างไม่น่าเชื่อเลยครับ! นอกจากจะไม่ต้อง lag กับ blur ของแท้แล้ว ขนาด texture ก็ประหยัด RAM ลงมากเลย
แต่เนื่องจาก blur ปลอมนี้เกิดจาก pixel interpolation แค่ไม่กี่สี (23 x 13 สี) ก็เลยจะเห็นเป็นดวงๆชัดเจนแบบนี้เลยว่าเดิมที pixel มันอยู่ตรงไหนในบางภาพ ที่เนียนน้อยกว่าภาพสีแดงนั่น
blur แท้ไม่มีปัญหานี้ ถ้าโชคร้ายไปโดน pixel สว่างๆเข้า (แต่รอบๆเป็นมืดหมดเลย) อาจจะเกิดผลที่ไม่ค่อยสวยได้ แต่เราก็สามารถใช้ Color ของ Raw Image พยายามย้อมสีให้มันเข้ากันๆได้ครับ
ถ้าปรับสีดำๆหน่อยก็จะจำลองเอฟเฟค Color Grading (มืดลงเท่านั้น เพราะขาวคือปกติ) ของ post-processing stack ได้ในตัวด้วย ไม่เหมือนเด๊ะเพราะมันดำแบบโง่ๆ (จริงๆอยากจะได้ดำแบบ overlay ของ Photoshop แต่กลัวเปลือง draw call) แต่ก็พอใช้ได้ครับ ลองบนมือถืออีกทีไม่ lag แล้วด้วย