φυβλαςのβλογ
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
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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