ใน
บทที่ ๒๗ ที่ผ่านมาเราสามารถใส่สีสันให้กับวัตถุได้แล้ว แต่ว่าใสบางครั้งแค่สีเรียบๆธรรมดาก็อาจจะไม่เพียงพอ อาจต้องการสีสันอะไรมากกว่านั้น
ดังนั้นจึงอาจต้องมีการนำภาพจากไฟล์ภาพที่มีอยู่แล้วมาใช้เพื่อตกแต่ง
การนำภาพมาใส่ในวัตถุในมายานั้นที่จริงก็คือกระบวนการเดียวกับการใส่สี เพียงแต่เปลี่ยนจากสีเดียวเป็นการใส่สีตามภาพที่เราต้องการ
กระบวนการ ใส่ภาพบนพื้นผิว NURBS กับโพลิกอนจะแตกต่างกันอยู่เล็กน้อย ดังนั้นจะขอแยกอธิบาย โดยเริ่มจากพื้นผิว NURBS ซึ่งค่อนข้างเรียบง่ายกว่า
ขอเริ่มยกตัวอย่างโดยลองใส่ภาพนี้ลงบนกระดาษแผ่นหนึ่ง เป็นรูปสาวน้อยเวทมนตร์มาโดกะ
ภาพตัวอย่างนำมาจาก
https://www.facebook.com/616507455065460 โดยมีการตัดขอบซ้ายขวาออกไปเพื่อให้ได้ภาพสัดส่วน 4:3
หากใครอยากจะลองทำตามตัวอย่างก็สามารถเซฟภาพนี้ไปใช้ หรืออาจหาภาพของตัวเองมาใช้ดูได้
ภาพที่ใช้จะเซฟใส่ไว้ในโฟลเดอร์ไหนก็ได้ แล้วให้เปลี่ยนพาธของไฟล์ในโค้ดให้เป็นไปตามนั้น
เช่น '
C:/ชื่อโฟลเดอร์/madokatokyube.jpg' เป็นต้น (ใช้ \ หรือ / ก็ได้)
โค้ดส่วนนี้ยาวเล็กน้อย แต่จะค่อยๆอธิบายทีละขั้นอย่างละเอียด
mc.shadingNode('phong',asShader=1,n='phap_madoka') # สร้างโหนดวัสดุ
mc.shadingNode('file',at=1,n='file_madoka') # สร้างโหนดเท็กซ์เจอร์ไฟล์ภาพ
mc.connectAttr('file_madoka.oc','phap_madoka.c') # เชื่อมโหนดวัสดุเข้ากับโหนดไฟล์ภาพ
s = '<พาธและชื่อไฟล์ภาพ>' # กำหนดไฟล์ภาพ
mc.setAttr('file_madoka.ftn',s,typ='string') # ตั้งพาธไฟล์ให้โหนดไฟล์ภาพ
mc.nurbsPlane(w=2,n='phaenkradat') # สร้างแผ่นกระดาษ
mc.rotate(0,0,45,p=[-1,0,0]) # หมุนให้หันขึ้นมาหน่อย
mc.hyperShade(a='phap_madoka') # ใส่วัสดุให้แผ่นกระดาษ
mc.shadingNode('place2dTexture',au=1,n='uv_madoka') # สร้างโหนด place2dTexture สำหรับปรับแต่งเท็กซ์เจอร์
mc.defaultNavigation(ce=1,s='uv_madoka',d='file_madoka') # เชื่อมโหนด place2dTexture เข้ากับโหนดเท็กซ์เจอร์ไฟล์ภาพ
ผลที่ได้ควรจะออกมาเป็นแบบนี้
ต่อไปเป็นคำอธิบายโค้ดทีละขั้น
เริ่มต้นทำเหมือนกันกับการใส่สีคือใช้ฟังก์ชัน shadingNode() โดยใส่แฟล็กเป็น asShader=1 สร้างโหนดของวัสดุขึ้น
จากนั้นขั้นตอนต่อไปก็คือต้องใช้ฟังก์ชัน shadingNode() อีกครั้งเพื่อสร้างโหนดขึ้นมาอีกโหนด ซึ่งคราวนี้สร้างเป็นหมวดเท็กซ์เจอร์ชนิดรูปภาพ ซึ่งทำได้โดยใส่แฟล็กเป็น at=1 และใส่ชนิดเป็น file
ซึ่งก็คือ mc.shadingNode('file',at=1,n='ชื่อโหนด')
จากนั้นก็ทำการเชื่อมต่อโหนดของวัสดุเข้ากับโหนดของเท็กซ์เจอร์โดยใช้ฟังก์ชัน connectAttr() ฟังก์ชันนี้มีไว้สำหรับเชื่อมโหนด ๒ โหนดเข้าด้วยกัน โดยการเชื่อมต่อนั้นจะเชื่อมที่ตัวองค์ประกอบของโหนดทั้ง ๒
ในที่นี้คือเชื่อมองค์ประกอบชื่อ oc (outColor) ของโหนดไฟล์ภาพเข้ากับองค์ประกอบ c (color) ของโหนดวัสดุภาพ ซึ่งจะมีความหมายว่า สีของไฟล์ภาพจะออกมากลายเป็นสีของวัสดุ
จากนั้นก็เชื่อมต่อโหนดวัสดุเข้ากับวัตถุที่ต้องการแปะภาพ เท่านี้ก็จะได้ภาพที่ต้องการมาอยู่บนพื้นผิวอย่างที่เห็น
อย่างไรก็ตาม ภาพที่ได้ตอนนี้จะเห็นว่าดูแล้วแปลกๆ เหมือนกับโดนบีบอัดให้แคบและสูงขึ้น นั่นเพราะปกติทันทีที่ใส่ภาพลงไป ตอนเริ่มแรกภาพจะถูกกางให้เต็มพื้นผิวทั้งหมด ถ้าสัดส่วนพื้นผิวไม่ตรงกับสัดส่วนของภาพต้นฉบับก็จะทำให้กลายเป็นแบบนี้ได้
ดังนั้นต่อไปจึงต้องเข้าสู่ขั้นตอนการปรับค่าอะไรต่างๆเพื่อให้ภาพแสดงผลได้ถูกต้องตามที่ต้องการ
การที่จะปรับการแสดงผลของภาพที่นำมาแปะได้นั้นจำเป็นต้องสร้างโหนดตัวขึ้นมาอีกโหนดเพื่อเป็นตัวช่วยเสริม
โหนดที่จะต้องสร้างขึ้นมาใหม่นั้นคือโหนดชนิด place2dTexture อยู่ในหมวด ยูทิลิตี (utility) สามารถสร้างขึ้นมาได้โดยใช้ฟังก์ชัน shadingNode() เช่นเดียวกันกับโหนดไฟล์ภาพ โดยเขียนเป็น mc.shadingNode('place2dTexture',au=1,n='ชื่อโหนด')
จากนั้นก็เชื่อมต่อโหนดนี้เข้ากับโหนดไฟล์ภาพ แต่คราวนี้ฟังก์ชันที่ต้องใช้คือ defaultNavigation()
ฟังก์ชันนี้มีไว้สำหรับเชื่อมต่อโหนดเข้าด้วยกันโดยจะเชื่อมในลักษณะที่ควรจะเป็น ซึ่งโปรแกรมกำหนดไว้อยู่แล้วว่าโหนดชนิดไหนเชื่อมกับโหนดชนิดไหนควรจะสร้าง ความสัมพันธ์ยังไง
การใช้ให้ใส่ชื่อของ ๒ โหนดที่ต้องการเชื่อมต่อกันไว้ในแฟล็ก s (source) และ d (destination) แล้วใส่แฟล็ก ce (connectToExisting) เป็น ce=1
ในที่นี้ใส่ s เป็นโหนดของ place2dTexture ส่วน d เป็นโหนดของไฟล์ภาพ
จากนั้นทั้ง ๒ โหนดนี้ก็จะเชื่อมต่อกันเรียบร้อย
ลองไปดูที่ไฮเพอร์เชด (วิธีเปิดดูใน
บทที่ ๒๗) แล้วคลิกขวาค้างที่โหนดวัสดุ แล้วเลือก Graph Network (グラフネットワーク) จะเป็นการแสดงกราฟเน็ตเวิร์ก
ก็จะพบความว่ามีกรอบวางเรียงรายกันอยู่ ๔ อัน ซึ่งแต่ละอันก็คือโหนดต่างๆ โดยมีเส้นเชื่อมกันอยู่ แสดงความสัมพันธ์
โหนดอันซ้ายสุดคือโหนด place2dTexture ส่วนถัดมาคือโหนดไฟล์ภาพ
สามารถคลี่ออกเพื่อดูรายละเอียดได้โดยกดปุ่มที่มุมขวาบน
คลี่ออกมาจะเห็นเส้นต่างๆมากมาย ทั้งหมดนี้คือสิ่งที่ฟังก์ชัน defaultNavigation() ได้ทำการเชื่อมโยงให้อัตโนมัติ
นอกจากการมาดูแผนผังนี้โดยตรงแล้ว ยังสามารถใช้ฟังก์ชัน listConnections() เพื่อตรวจดูว่าแต่ละโหนดนั้นมีการเชื่อมโยงอยู่กับอะไรบ้างได้ โดยใส่ชื่อโหนดที่ต้องการค้นความสัมพันธ์ จากนั้นถ้าต้องการให้แสดงชื่อขององค์ประกอบที่ถูกเชื่อมด้วยก็ให้ใส่แฟล็ก c=1 และ p=1
ลองพิมพ์
s = mc.listConnections('uv_madoka',c=1,p=1)
for i in range(0,len(s),2):
print(s[i]+' \t '+s[i+1])
ก็จะได้รายชื่อขององค์ประกอบที่เชื่อมโยงกันทั้งหมด
ทั้งหมดนี้เป็นองค์ประกอบที่จำเป็นต้องเชื่อมเพื่อให้ค่าที่ปรับในโหนด place2dTexture มีผลต่อการแสดงผลของโหนดไฟล์ภาพ
หากจะเชื่อมทั้งหมดนี้เองโดยใช้ฟังก์ชัน connectAttr() ก็ได้เช่นกัน โดยการพิมพ์
mc.connectAttr('uv_madoka.outUV','file_madoka.uvCoord')
mc.connectAttr('uv_madoka.outUvFilterSize','file_madoka.uvFilterSize')
mc.connectAttr('uv_madoka.coverage','file_madoka.coverage')
mc.connectAttr('uv_madoka.translateFrame','file_madoka.translateFrame')
mc.connectAttr('uv_madoka.rotateFrame','file_madoka.rotateFrame')
mc.connectAttr('uv_madoka.mirrorU','file_madoka.mirrorU')
mc.connectAttr('uv_madoka.mirrorV','file_madoka.mirrorV')
mc.connectAttr('uv_madoka.stagger','file_madoka.stagger')
mc.connectAttr('uv_madoka.wrapU','file_madoka.wrapU')
mc.connectAttr('uv_madoka.wrapV','file_madoka.wrapV')
mc.connectAttr('uv_madoka.repeatUV','file_madoka.repeatUV')
mc.connectAttr('uv_madoka.vertexUvOne','file_madoka.vertexUvOne')
mc.connectAttr('uv_madoka.vertexUvTwo','file_madoka.vertexUvTwo')
mc.connectAttr('uv_madoka.vertexUvThree','file_madoka.vertexUvThree')
mc.connectAttr('uv_madoka.vertexCameraOne','file_madoka.vertexCameraOne')
mc.connectAttr('uv_madoka.noiseUV','file_madoka.noiseUV')
mc.connectAttr('uv_madoka.offset','file_madoka.offset')
mc.connectAttr('uv_madoka.rotateUV','file_madoka.rotateUV')
ซึ่งเยอะและยาวกว่ามาก และอาจมีการตกหล่นได้ ดังนั้นโดยทั่วไปแล้วใช้ defaultNavigation() ทีเดียวเลยดีกว่า
อันที่จริงไม่มีความจำเป็นจะต้องเชื่อมองค์ประกอบทั้งหมด เชื่อมแค่ค่าที่ต้องการจะใช้เท่านั้นก็พอ
ตอนนี้การเตรียมการทุกอย่างก็พร้อมแล้ว ขั้นตอนต่อไปจะมาลองปรับค่าต่างๆภายในโหนด place2dTexture
สามารถกดเลือกโหนดนั้นได้โดยผ่านทางกราฟเน็ตเวิร์กในไฮเพอร์เชดเมื่อครู่ หรืออาจเข้าไปที่หมวด
Utility (ユーティリティ) แล้วเลือก
หรืออาจใช้ฟังก์ชัน select() เพื่อเลือกก็ได้ ในที่นี้พิมพ์
mc.select('uv_madoka')
จากนั้นดูที่แอตทริบิวต์อีดิเตอร์ก็จะเห็นค่าอะไรต่างๆมากมายที่สามารถปรับได้ เช่น
c |
(coverage) |
有効範囲 |
= ขอบเขตแสดงผล |
แบ่งเป็นแนวแกน U และ V: cu (coverageU) และ cv (coverageV) |
tf |
(translateFrame) |
フレームの移動 |
= การเคลื่อนย้ายเฟรม |
แบ่งเป็นแนวแกน U และ V: tfu (translateFrameU) และ tfv (translateFrameV) |
rf |
(rotateFrame) |
フレームの回転 |
= การหมุนเฟรม |
mu |
(mirrorU) |
ミラーU |
= สะท้อน U |
mv |
(mirrorV) |
ミラーV |
= สะท้อน V |
s |
(stagger) |
スタッカー |
= สลับฟันปลา |
re |
(repeatUV) |
繰り返しUV |
= วนซ้ำ UV |
แบ่งเป็นแนวแกน U และ V: reu (repeatU) และ rev (repeatV) |
of |
(offset) |
オフセット |
= อ็อฟเซ็ต |
แบ่งเป็นแนวแกน U และ V: ofu (offsetU) และ ofv (offsetV) |
r |
(rotateUV) |
UVの回転 |
= การหมุน UV |
n |
(noiseUV) |
ノイズUV |
= UV คลื่นรบกวน |
แบ่งเป็นแนวแกน U และ V: nu (noiseU) และ nv (noiseV) |
เริ่มแรกลองเริ่มจากทำให้ภาพแสดงผลเป็นสัดส่วนที่ถูกต้องก่อน สามารถทำได้หลายวิธี
เนื่องจากสัดส่วนเดิมของภาพเป็น 4:3 แต่ถูกบีบให้อยู่ในพื้นที่ 1:1 ทำให้ภาพแคบลง ดังนั้นต้องปรับด้านกว้างให้กว้างขึ้น หรือปรับด้านสูงให้แคบลง
ในที่นี้จะลองปรับด้านกว้างให้กว้างขึ้นโดยปรับขอบเขตของภาพ โดยปรับที่ค่า cu (coverageU) ซึ่งเป็นค่าความกว้างของขอบเขตภาพในหน่วยจำนวนเท่าของความกว้างพื้นผิว
พอ ทำแบบนี้แล้วก็จะได้ภาพที่ขยายออกไปเป็น 1.333 เท่า กลายเป็นตามสัดส่วนจริง แต่ว่าเนื่องจากภาพกว้างขึ้นจึงด้านออกไปทางด้านขวาจนตกขอบมองไม่เห็น
แก้ปัญหาด้วยการเลื่อนภาพไปทางซ้าย การเลื่อนตำแหน่งต้องปรับที่ค่า tf (translateFrame) ค่าตำแหน่งนี้ก็ใช้เป็นหน่วยจำนวนเท่าของความกว้างผิว
mc.setAttr('uv_madoka.tfu',-0.333)
mc.setAttr('uv_madoka.cu',1.333)
การหมุนภาพทำได้ด้วยการปรับค่า rf (rotateFrame)
mc.setAttr('uv_madoka.rf',-30)
แต่ถ้าแค่หมุนไปก็จะเห็นว่าภาพแหว่งหายไปไม่เต็มส่วน คราวนี้ลองขยายภาพเพิ่มแล้วก็เลื่อนตำแหน่งให้เห็นหัวพอดี
mc.setAttr('uv_madoka.c',4,3)
mc.setAttr('uv_madoka.tf',-2.6,-1.7)
อีกค่าที่อาจลองปรับดูก็คือ re (repeatUV) ซึ่งเป็นจำนวนของภาพที่ต้องการให้ซ้ำ ถ้าตั้งให้มากกว่า 1 ภาพก็จะเล็กลงแต่วนซ้ำทำให้จำนวนเพิ่มขึ้น
ลองปรับค่า ๓ อย่างแรก (rf, c, tf) ให้กลับเป็นค่าเริ่มต้นก่อนแล้วค่อยตั้งค่า re
mc.setAttr('uv_madoka.rf',0)
mc.setAttr('uv_madoka.c',1,1)
mc.setAttr('uv_madoka.tf',0,0)
mc.setAttr('uv_madoka.re',3,4)
จะได้ภาพเล็กๆออกมา ๑๒ ภาพ
ภาพ ที่วนซ้ำนี้สามารถทำให้กลับด้านไปมาได้โดยปรับ mu (mirrorU) และ mv (mirrorV) ซึ่งแรกเริ่มจะเป็น 0 คือไม่มีการกลับด้าน ถ้าปรับให้เป็น 1 ก็จะกลับด้าน
mc.setAttr('uv_madoka.mu',1)
mc.setAttr('uv_madoka.mv',1)
ถ้าปรับค่า s (stagger) การกลับด้านในแต่ละแถวก็จะสลับฟันปลา
mc.setAttr('uv_madoka.s',1)
ถ้าปรับค่า of (offset) ก็จะเป็นการเลื่อนตำแหน่ง แต่หน่วยในที่นี้คือจำนวนเท่าของความกว้างของภาพที่ย่อแล้ว
mc.setAttr('uv_madoka.of',0.6,0.2)
ส่วนค่า n (noiseUV) คือคลื่นรบกวน ถ้าปรับจะทำให้ภาพบิดเบี้ยวเหมือนมองผ่านผิวน้ำที่มีคลื่นซัดไปมา
mc.setAttr('uv_madoka.n',0.03,0.03)
นอกจากนี้ภาพจะเปลี่ยนไปตามพื้นผิวที่ถูกวาง หากมีการเปลี่ยนแปลงพื้นผิวดูก็จะพบว่าภาพถูกดึงตามไปด้วย เหมือนผืนผ้า
ลองปรับรูปแผ่นกระดาษดู
mc.setAttr('uv_madoka.n',0,0) # ลบคลื่นรบกวนออกไปก่อน
mc.setAttr('uv_madoka.re',1,1) # ปรับขนาดให้เท่าเดิม
mc.setAttr('uv_madoka.of',0,0) # ดึงภาพกลับมาตรงกลาง
for i in [0,3]:
mc.scale(1,1,3,'phaenkradat.cv[%d][*]'%i) # ยืดส่วนขอบไปซ้ายขวา
for i in [1,2]:
mc.scale(3,3,1,'phaenkradat.cv[%d][*]'%i) # ยืดส่วนกลางๆไปบนล่าง
ลองสร้างใหม่โดยนำภาพมาแปะบนทรงกระบอกก็ได้ (ก่อนสร้างให้เริ่มฉากใหม่ก่อน)
mc.shadingNode('phong',asShader=1,n='phap_madoka')
mc.shadingNode('file',at=1,n='file_madoka')
mc.connectAttr('file_madoka.oc','phap_madoka.c')
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('file_madoka.ftn',s,typ='string')
mc.cylinder(r=1,hr=2*3.14159*4/3,n='krabok')
mc.hyperShade(a='phap_madoka')
mc.shadingNode('place2dTexture',au=1,n='uv_madoka')
mc.defaultNavigation(ce=1,s='uv_madoka',d='file_madoka')
สำหรับทรงกลมนั้น มีภาพบางชนิดที่ถูกสร้างขึ้นไว้เพื่อให้แปะลงบนทรงกลมได้พอดี นั่นคือด้านบนกับล่างสุดจะขยายกว้างมาก เช่นภาพแผนที่โลก จะเห็นว่ากรีนแลนด์กับแอนตาร์กติกาดูเหมือนใหญ่มากมายเพราะว่าอยู่ใกล้ขั้วโลก แต่ความจริงพอนำมาแปะบนลูกโลกก็จะเห็นว่ามันไม่ได้ใหญ่ขนาดนั้น
(คลิกเพื่อดูภาพเต็ม) ที่มาของภาพ จาก
http://members2.jcom.home.ne.jp/planet.earth/four_seasons.html ลองเอาภาพแผนที่โลกนี้มาแปะลงบนทรงกลมจะได้ภาพลูกโลกตามที่ควรเป็นพอดี
mc.shadingNode('phong',asShader=1,n='phap_lok')
mc.shadingNode('file',at=1,n='file_lok')
mc.connectAttr('file_lok.oc','phap_lok.c')
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('file_lok.ftn',s,typ='string')
mc.sphere(r=200,n='luklok',nsp=36,s=36,ax=[0,1,0])
mc.hyperShade(a='phap_lok')
mc.shadingNode('place2dTexture',au=1,n='uv_lok')
mc.defaultNavigation(ce=1,s='uv_lok',d='file_lok')
mc.setAttr('uv_lok.rf',90)
สรุปขั้นตอนการใส่ภาพบนพื้นผิว NURBS
๑.
mc.shadingNode('<ชนิดวัสดุ>',asShader=1,n='<ชื่อโหนดวัสดุ>') สร้างโหนดวัสดุที่ใช้เป็นภาพ
๒.
mc.shadingNode('file',at=1,n='<ชื่อโหนดไฟล์ภาพ>') สร้างโหนดเท็กซ์เจอร์ชนิดไฟล์
๓.
mc.connectAttr('<ชื่อโหนดไฟล์ภาพ>.oc','<ชื่อโหนดวัสดุ>.c') เชื่อมต่อโหนดไฟล์ภาพกับโหนดวัสดุ
๔.
mc.setAttr('<ชื่อโหนดไฟล์ภาพ>.ftn',<พาธและชื่อไฟล์ภาพ>,typ='string') ระบุไฟล์ที่เก็บภาพ
๕.
mc.shadingNode('place2dTexture',au=1,n='<ชื่อโหนด>') สร้างโหนดยูทิลิตีชนิด place2dTexture
๖.
mc.defaultNavigation(ce=1,s='<ชื่อโหนด place2dTexture>',d='<ชื่อโหนดไฟล์ภาพ>') เชื่อมต่อโหนด place2dTexture เข้ากับโหนดไฟล์ภาพ
๗.
mc.select('<ชื่อวัตถุหรือผิว>') เลือกวัตถุที่ต้องการแปะภาพ
๘.
mc.hyperShade(a='<ชื่อโหนดไฟล์ภาพ>') เชื่อมต่อโหนดวัสดุภาพเข้ากับวัตถุหรือผิว
๙. ปรับค่าองค์ประกอบต่างๆในโหนด place2dTexture เพื่อให้ได้ภาพที่วางในตำแหน่งตามที่ต้องการ
อ้างอิง