ในตอนที่ผ่านมาได้ปรับแต่งลวดลายสีสันให้พื้นผิวเป็นอะไรต่างๆได้อย่างอิสระแล้ว
แต่ว่าพื้นผิวนั้นนอกจากสีสันแล้วก็ยังมีอีกหลายอย่างที่สามารถปรับได้ สำหรับบทนี้จะพูดถึงเรื่องการปรับระดับความสูงของผิว
โดยทั่วไปแล้วภาพสามมิติเราจะรู้สึกถึงมิติรูปร่างของวัตถุได้ด้วยการปรับผิวของวัตถุให้มีการนูนขึ้นหรือเว้าลง
อย่างไรก็ตามการทำแบบนั้นเป็นการเพิ่มจำนวนโพลิกอนซึ่งทำให้โปรแกรมต้องทำงานหนัก
ในกรณีที่แค่ต้องการปรับพื้นผิวสร้างมิติให้มีความนูนเว้าของวัตถุขึ้นมาเล็กน้อยเราสามารถใช้การปรับแต่งพื้นผิวด้วยวิธีที่เรียกว่า
บัมป์แม็ปปิง (バンプ マッピング, bump mapping) ซึ่งเป็นวิธีการปรับพื้นผิวให้ดูเหมือนมีความสูงต่ำดูมีมิติขึ้นมาโดยที่ไม่ต้องสร้างโพลิกอนเพิ่มหรือดัดผิวให้นูนเว้าขึ้นมาจริงๆ
อย่างไร ก็ตามการใช้บัมป์แม็ปปิงนั้นแท้จริงแล้วเป็นแค่การเล่นแสงเงาโดยการเปลี่ยน มุมตกกระทบของแสงให้ดูเหมือนพื้นนูนเว้าขึ้นมาเท่านั้น ผิวไม่ได้นูนขึ้นมาจริงๆ
ซึ่งต่างจากอีกวิธีหนึ่งคือ
ดิสเพลซเมนต์แม็ปปิง (ディスプレイスメント マッピング, displacement mapping) ซึ่งเป็นการสร้างโพลิกอนให้นูนขึ้นมาจริงๆตอนที่เรนเดอร์
ดิสเพลซเมนต์แม็ปปิงทำผิวนูนเว้าได้สมจริงกว่า แต่ก็เป็นเทคนิกขั้นสูงกว่า และต้องใช้เวลาเรนเดอร์นานกว่า ในที่นี้จะยังไม่พูดถึง
หากไม่ได้ต้องการภาพที่สมจริงมากมายนักการใช้แค่บัมป์แม็ปปิงก็เพียงพอ แล้วแต่ความต้องการในการใช้งาน
หลัก การของบัมป์แม็ปปิงก็คือการนำภาพหรือลวดลายบางอย่างมาใช้เป็นตัวบอกความสูง ของพื้นผิว โดยทั่วไปแล้วใช้สีเข้มแทนผิวต่ำ สีอ่อนแทนผิวสูง ดังนั้นเราสามารถเก็บความสูงของผิวในรูปแบบภาพสีโทนเดียวได้
เหมือนแผนที่ภูมิศาสตร์ของโลกที่ใช้สีต่างๆแทนความสูงของระดับพื้นผิวและความลึกของทะเลนั่นเอง
การทำบัมป์แม็ปปิงนั้นมีขั้นตอนวิธีการคล้ายกับการใส่สีใส่ลายให้วัตถุ เพียงแต่เปลี่ยนจากการตั้งสีเป็นตั้งบัมป์แม็ปปิงเท่านั้น จะใช้ไฟล์ภาพก็ได้หรือใช้ลายที่โปรแกรมมีอยู่แล้วก็ได้
เพื่อให้เห็นภาพลองมาเริ่มดูตัวอย่างกันเลย ลองทำพื้นที่มีลายโดยใช้ลายเป็นภาพนี้
mc.shadingNode('blinn',asShader=1,n='phiu_phuen') # สร้างโหนดวัสดุพื้น
mc.shadingNode('bump2d',au=1,n='nun_phuen') # สร้างโหนด bump2d
mc.shadingNode('file',at=1,n='file_phuen') # สร้างโหนดไฟล์ภาพ
mc.connectAttr('nun_phuen.o','phiu_phuen.n') # เชื่อมต่อโหนด
mc.connectAttr('file_phuen.oa','nun_phuen.bv') # เชื่อมต่อโหนด
mc.setAttr('phiu_phuen.c',0.8,0.3,0.1,typ='double3') # ใส่สีให้วัสดุพื้น
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('file_phuen.ftn',s,typ='string')
mc.polyPlane(w=10,h=10,sx=1,sy=1,n='phuen') # สร้างพื้น
mc.hyperShade(a='phiu_phuen') # ใส่วัสดุให้พื้น
ผลที่ได้จะเห็นว่าตรงที่ในภาพเป็นพื้นสีเข้มจะปรากฏเป็นลักษณะบุ๋มต่ำลงไป ดูแล้วเหมือนพื้นมีร่องตามเส้นจริงๆ
จะเห็นว่าสิ่งที่ต้องเพิ่มเข้ามาเมื่อเทียบกับการใช้ภาพเป็นสีก็คือ ต้องเพิ่มโหนด bump2d ขึ้นมา โดยโหนดนี้จะเป็นโหนดยูทิลิตีที่เชื่อมระหว่างโหนดเท็กซ์เจอร์ไฟล์และโหนด วัสดุอีกที ซึ่งการเชื่อมก็ใช้ connectAttr สองต่อตามในตัวอย่างนี้
ระดับความนูนเว้าของผิวสามารถปรับแก้ได้ที่ค่า bd (bumpDepth) ของโหนด bump2d ยิ่งค่ามากก็ยิ่งรู้สึกถึงความต่างระดับของผิวมาก
ถ้าค่าติดลบจะกลายเป็นว่าส่วนที่สีเข้มดูเหมือนนูนขึ้นมาแทน เช่นลอง
mc.setAttr('nun_phuen.bd',-1.2)
แบบนี้ส่วนเส้นจะกลายเป็นลายนูนขึ้นมาแทน
ต่อมา ลองใช้ลวดลายที่โปรแกรมมีอยู่แล้วเป็นตัวกำหนดค่านูนเว้าดูบ้าง
เช่นใช้ลายผ้า
mc.shadingNode('phong',asShader=1,n='phiu_phuen2')
mc.shadingNode('bump2d',au=1,n='nun_phuen2')
mc.shadingNode('cloth',at=1,n='lai_phuen2')
mc.connectAttr('nun_phuen2.o','phiu_phuen2.n')
mc.connectAttr('lai_phuen2.oa','nun_phuen2.bv')
mc.setAttr('phiu_phuen2.c',0.9,0.1,0.1,typ='double3')
mc.polyPlane(w=10,h=10,sx=1,sy=1,n='phuen2')
mc.hyperShade(a='phiu_phuen2')
mc.setAttr('nun_phuen2.bd',-1.2)
mc.polyProjection('phuen2.f[0]',rx=90,psu=3,psv=3)
mc.setAttr('nun_phuen2.bd',5)
หากใช้ลวดลายเพื่อแทนความนูนเว้าของผิวแบบนี้แล้วก็สามารถทำภาพพื้นผิวที่มีการเคลื่อนไหวได้โดยง่าย
ลองทำผิวน้ำที่เคลื่อนไหวดู
mc.shadingNode('phong',asShader=1,n='phiu_nam') # สร้างโหนดวัสดุผิวน้ำ
mc.setAttr('phiu_nam.c',0,0.6,1,typ='double3') # กำหนดสีเป็นสีฟ้า
mc.shadingNode('water',at=1,n='lai_nam') # สร้างโหนดเท็กซ์เจอร์ลายน้ำ
mc.shadingNode('bump2d',au=1,n='nun_nam') # สร้างโหนด bump2d
mc.connectAttr('nun_nam.o','phiu_nam.n') # เชื่อมต่อโหนด
mc.connectAttr('lai_nam.oa','nun_nam.bv')
mc.polyPlane(w=4,h=4,sx=1,sy=1,n='nam') # สร้างแผ่นผิวน้ำ
mc.hyperShade(a='phiu_nam') # ใส่วัสดุให้ผิวตาราง
mc.setAttr('lai_nam.wa',1) # ปรับความสูงของคลื่นน้ำ
mc.setKeyframe('lai_nam',at='wt',v=0,t=0) # ตั้งคีย์เฟรมเวลาเริ่มต้น
mc.setKeyframe('lai_nam',at='wt',v=1,t=200) # ตั้งคีย์เฟรมเวลาปลาย
ลองทำกับผิวทรงกลมเช่นดวงดาวดูบ้าง คราวนี้ใช้ภาพนี้แทนความสูงของพื้นผิวดาว
ที่มาของภาพ
http://kexitt.deviantart.com/art/Mimas-height-map-585731767 นี่คือดวงจันทร์มีมาส ดาวบริวารดวงหนึ่งของดาวเสาร์ มีจุดเด่นคือมีหลุมขนาดใหญ่อยู่กลางดาว
mc.shadingNode('blinn',asShader=1,n='phiu_mimas') # สร้างโหนดวัสดุ
mc.shadingNode('place2dTexture',au=1,n='uv_mimas') # สร้างโหนด place2dTexture
mc.shadingNode('bump2d',au=1,n='nun_mimas') # สร้างโหนด bump2d
mc.shadingNode('file',at=1,n='file_mimas') # สร้างโหนดไฟล์ภาพ
mc.defaultNavigation(ce=1,s='uv_mimas',d='file_mimas') # เชื่อมต่อโหนด
mc.connectAttr('nun_mimas.o','phiu_mimas.n')
mc.connectAttr('file_mimas.oa','nun_mimas.bv')
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('file_mimas.ftn',s,typ='string')
mc.setAttr('uv_mimas.rf',90)
mc.sphere(r=200,ax=[0,1,0],n='daomimas') # สร้างทรงกลมดาว
mc.hyperShade(a='phiu_mimas') # ใส่วัสดุบนผิวดาว
ให้ระวังว่าแผนที่ของความสูงดาวที่แสดงด้วยสีนั้นจะต่างจากสีผิวดาวจริงๆ ถ้าเอาสีผิวดาวจริงมาใช้จะไม่ได้ผลอย่างที่ต้องการ
เช่นดวงจันทร์ของโลกเรานั้นสีพื้นผิวที่ปรากฏเห็นจะเป็นแบบนี้
แต่แผนที่แสดงความสูงของพื้นจะเป็นแบบนี้
ที่มาของภาพ
http://www.johnstonsarchive.net/spaceart/cylmaps.html คราวนี้ลองสร้างดวงจันทร์โดยใส่ทั้งสีผิวและความสูงของพื้นพร้อมกันได้เลย สามารถใช้ภาพทั้งสองนี้พร้อมกันได้ โดยภาพหนึ่งสร้างบัมป์แม็ปปิงและอีกภาพกำหนดสี
mc.shadingNode('phong',asShader=1,n='phiu_duangchan') # สร้างโหนดวัสดุ
mc.shadingNode('place2dTexture',au=1,n='uv_duangchan') # สร้างโหนด place2dTexture
mc.shadingNode('bump2d',au=1,n='nun_duangchan') # สร้างโหนด bump2d
mc.shadingNode('file',at=1,n='file_khwangsungphiuduangchan') # สร้างโหนดไฟล์ภาพความสูงผิว
mc.shadingNode('file',at=1,n='file_siphiuduangchan') # สร้างโหนดไฟล์ภาพสีผิว
mc.defaultNavigation(ce=1,s='uv_duangchan',d='file_khwangsungphiuduangchan')
mc.defaultNavigation(ce=1,s='uv_duangchan',d='file_siphiuduangchan')
mc.connectAttr('nun_duangchan.o','phiu_duangchan.n')
mc.connectAttr('file_khwangsungphiuduangchan.oa','nun_duangchan.bv')
mc.connectAttr('file_siphiuduangchan.oc','phiu_duangchan.c')
s = '<พาธและชื่อไฟล์ภาพระดับความสูงพื้น>'
mc.setAttr('file_khwangsungphiuduangchan.ftn',s,typ='string')
s = '<พาธและชื่อไฟล์ภาพสีพื้น>'
mc.setAttr('file_siphiuduangchan.ftn',s,typ='string')
mc.setAttr('uv_duangchan.rf',90)
mc.sphere(r=200,ax=[0,1,0],n='duangchan')
mc.hyperShade(a='phiu_duangchan')
จะได้ดวงจันทร์ที่มีทั้งสีอ่อนเข้มและมิติความสูงต่ำ
สรุปขั้นตอนการทำบัมป์แม็ปปิง
๑.
mc.shadingNode('<ชนิดวัสดุ>',asShader=1,n='<ชื่อโหนดวัสดุ>') สร้างโหนดวัสดุที่ใช้
๒.
mc.shadingNode('file',at=1,n='<ชื่อโหนดไฟล์ภาพ>') สร้างโหนดเท็กซ์เจอร์ไฟล์ภาพ
๓.
mc.shadingNode('bump2d',au=1,n='<ชื่อโหนด bump2d>') สร้างโหนด bump2d
๔.
mc.connectAttr('<ชื่อโหนด bump2d>.o','<ชื่อโหนดวัสดุ>.n') เชื่อมต่อโหนด bump2d กับโหนดวัสดุ
๕.
mc.connectAttr('<ชื่อโหนดไฟล์ภาพ>.oa','<ชื่อโหนด bump2d>.bv') เชื่อมต่อโหนดไฟล์ภาพกับโหนด bump2d
๖.
mc.setAttr('<ชื่อโหนดไฟล์ภาพ>.ftn',<พาธและชื่อไฟล์ภาพ>,typ='string') ระบุไฟล์ที่เก็บภาพ
๗.
mc.select('<ชื่อวัตถุหรือผิว>') เลือกวัตถุที่ต้องการแปะภาพ
๘.
mc.hyperShade(a='<ชื่อโหนดไฟล์ภาพ>') เชื่อมต่อโหนดไฟล์ภาพเข้ากับวัตถุหรือผิว
กรณีที่ใช้ลายที่มีอยู่แล้วก็แค่เปลี่ยนข้อ ๒. จาก file เป็นชนิดพื้นผิว ส่วน ๖. ก็กลายเป็นการตั้งค่าของลาย
นอกจากนั้นหากต้องปรับการจัดวางพื้นผิวก็เพิ่ม shadingNode('place2dTexture',au=1) สำหรับผิว NURBS หรือเพิ่ม polyProjection() สำหรับโพลิกอน
ตอนนี้เราสามารถแต่งพื้นผิววัตถุได้หลากหลายขึ้นมากแล้ว ไม่เพียงแต่สร้างสีสันแต่ยังทำให้พื้นผิวดูมีมิติขึ้นมาได้แล้ว
อ้างอิง