φυβλαςのβλογ
บล็อกของ phyblas



maya python เบื้องต้น บทที่ ๓๗: การทำพื้นผิวนูนเว้า
เขียนเมื่อ 2016/03/15 01:29
แก้ไขล่าสุด 2021/09/28 16:42
ในตอนที่ผ่านมาได้ปรับแต่งลวดลายสีสันให้พื้นผิวเป็นอะไรต่างๆได้อย่างอิสระแล้ว

แต่ว่าพื้นผิวนั้นนอกจากสีสันแล้วก็ยังมีอีกหลายอย่างที่สามารถปรับได้ สำหรับบทนี้จะพูดถึงเรื่องการปรับระดับความสูงของผิว

โดยทั่วไปแล้วภาพสามมิติเราจะรู้สึกถึงมิติรูปร่างของวัตถุได้ด้วยการปรับผิวของวัตถุให้มีการนูนขึ้นหรือเว้าลง

อย่างไรก็ตามการทำแบบนั้นเป็นการเพิ่มจำนวนโพลิกอนซึ่งทำให้โปรแกรมต้องทำงานหนัก

ในกรณีที่แค่ต้องการปรับพื้นผิวสร้างมิติให้มีความนูนเว้าของวัตถุขึ้นมาเล็กน้อยเราสามารถใช้การปรับแต่งพื้นผิวด้วยวิธีที่เรียกว่าบัมป์แม็ปปิง (バンプ マッピング, 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() สำหรับโพลิกอน



ตอนนี้เราสามารถแต่งพื้นผิววัตถุได้หลากหลายขึ้นมากแล้ว ไม่เพียงแต่สร้างสีสันแต่ยังทำให้พื้นผิวดูมีมิติขึ้นมาได้แล้ว



อ้างอิง

<< บทที่แล้ว      บทถัดไป >>
หน้าสารบัญ


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> mayapython
-- คอมพิวเตอร์ >> 3D >> maya

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文