Displacement Map
สร้างฉากใต้ทะเล โดยใช้ Displacement Map
Chamferbox
ขั้นตอนการสร้าง เตียง ผ้าคลุมเตียง หมอนใบนั้น
Compesite Map
ขั้นตอนการสร้างวัสดุ น้ำ Compesite Map

[Introduction to Shading Language Part 4]
Displacement Shader
Displacement คือเทคนิกที่สามารถทำให้พื้นผิวสามารถนูนหรือยุบได ้หรือถ้าพูดให้ถูก Displacement คือการเลื่อนจุด P ไปจากตำแหน่งเดิม ตามค่าที่กำหนด หรือ จุด P อยู่ตำแหน่งเดิม แต normal vector ของจุด P เปลี่ยนไป
ใน Maya เรียกการเลื่อนจุด P ให้ไปอยู่ในตำแหน่งใหม่ว่า Displacement และเรียกการเปลี่ยนเฉพาะ normal vector ว่า Bump...
เทกนิกทั้งสองอย่างนี้มีประโยชน์อย่างมากในการสร้างงานที่มีคุณภาพสูง เช่นการทำผิวไดโนเสาร ์การสร้างให้มีรายละเอียด โดยการขึ้น โมเดลทั้งหมด เป็น เรื่องที่เสียเวลาและ ต้องใช้เครื่องที่มีความเร็วสูง และหน่วยความจำจำนวนมาก หลังจากทำเสร็จก็จะพบปัญหา ที่ตามมามากมาย เช่น เปลืองเวลาในการทำ Skin deformation เยอะมาก เนื่องจากจุดเยอะมาก ดังนั้นการทำ Displacement จึงเป็นที่นิยมอย่างมากในการทำงานที่ต้องการคุณภาพสูง
RenderMan
ใน RenderMan เราสามารถสร้าง Displacement Shader อย่างง่ายขึ้นมาได้โดยการบวก N เดิมของ P เข้ากับระยะ Displecment ที่ต้องการ
P += bumpHeight * normalize(N); N = calculatenormal(P);
2 บรรทัดด้านบนนี้คือตัวอย่างการทำงานของ Displacement อย่างง่าย เมื่อ P เป็น vector บอกตำแหน่งของจุด เราจึงสามารถเลื่อนตำแหน่ง ได้โดยการ บวกกับ normal vector ของจุด P นั่นเอง bumpHeight คือตัวคูณที่เป็นตัวกำหนดว่าจะเลื่อนตำแหน่งของ P ไปมากเท่าไหร ่
ส่วนบรรทัดล่างคือการคำนวณ N ใหม ่เนื่องจากเมื่อ P เปลี่ยนตำแหน่ง normal vector ที่จุด P มัดจะเปลี่ยนด้วย จึงต้องคำนวณค่าใหม ่ขั้นตอนนี้RenderMan ไม่ทำให้อัตโนมัติเนื่องจาก normal vector ไม่จำเป็นต้องขึ้นกับรูปร่างของพื้นผิวเสมอไป
Bump Mapping
ถ้าต้องการ Bump เพียงอย่างเดียว เราสามารถหด เหลือเพียงบรรทัดเดียวได N = calculatenormal(P + bumpHeight*normalize(N)); เป็นการเปลี่ยนค่า N เพียงอย่างเดียวเท่านั้น โดยไม่เปลี่ยนค่า P จึงไม่ทำให้พื้นผิว เปลี่ยนรูปร่าง ลองมาดูตัวอย่างซักอันครับ

ภาพนึ้เป็นการใช้งาน Displacement ซึ่งเปลี่ยนตำแหน่ง P รวมกับ Bump ซึ่งเปลี่ยนเพียง N เท่านั้น มาดูกันครับ ว่าต้องเตรียมอะไรบ้าง
slim 1 extensions pixardb

{ extensions pixar pxsl

{

template displacement xDisplacement {

label xDisplacement description "Combining simple displacement and bump shader together."

ribattribute float displacementbound {

label "Displacement Bound" description "This number represents the maximum displacement in shaderspace that your surface will undergo. Be very careful with this parameter as it can dramatically influence rendering times. In particular, make SURE to set this to 0 (zero) if you aren't performing any displacement."

default 0 range

{0 100 .001}

subtype vslider

}

parameter float DoDisplacement {

label "Do Displacement" default 0 subtype switch

}

parameter float UseShadingNormals {

label "Use Shading Normals" description "When a displacement map is used, this shader calls calculatenormal().This causes polygonal data to appear faceted. This parameter causes the original shading normal offset to be added to the calculated normal, generally re-smoothing polygonal data." default 0 subtype switch

}

parameter float Kb0 { description "A multiplier for the bump."

subtype vslider range {0 100 .001} detail varying default .1

}

parameter float Bump {

detail mustvary default 0

}

parameter float Kb1 { description "A multiplier for the displacement." subtype vslider range {0 100 .001} detail varying default .1 }

parameter float Displacement { detail mustvary default 0 } RSLMain

{

output "normal Nf;"
output "point PP = transform(\"shader\", P);"
output "point Q = transform(\"shader\", P);"
generate
output "Nf = normalize( ntransform(\"shader\", N) );"
output "PP += [getvar Kb0] * [getvar Bump]*Nf;"
output "PP += [getvar Kb1] * [getvar Displacement]*Nf;"
output "PP = transform(\"shader\", \"current\", PP);"
output "Q += [getvar Kb1] * [getvar Displacement]*Nf;"
output "Q = transform(\"shader\", \"current\", Q);"
output "if([getvar UseShadingNormals] != 0) { "
output " normal deltaN = normalize(N) - normalize(Ng);"
output " N = normalize(calculatenormal(PP)) + deltaN;"
output "} else {"
output " N = calculatenormal(PP);"
output "}"
output "if([getvar DoDisplacement] != 0)"
output " P = Q;"

} } } }
ด้านบนนี้คือ Slim Template เช่นเคย คงจะเริ่มคุ้นกันแล้วนะครับ เป็นการดัดแปลงจาก displcement.slim ที่มากับ RAT โดยเพิ่มตัวแปล Kb0 และ Kb1

ลงไป PP รับหน้าที่เก็บตำแหน่งของ P เมื่อถูก เลื่อนสองครั้ง จาก Kb0 และ Kb1 จึงเป็นจุดที่ใช้คำนวญ normal vector สุดท้าย Q ทำหน้าที่เก็บตำแหน่งของ P เมื่อถูกเลื่อนไป ครั้งเดียว จากค่า Kb1 (Displacement) เป็นตัวเก็บตำแหน่งจริงของ P เสร็จเรองเขียน Shader ก็มาถึง Maya กันครับ

เป็น Model ที่สร้างด้วย Polygon และเปลี่ยนเป็น Subdiv Surfaces เนื่องจากเป็น Polygon จึงต้องมีการคลี่UV เป็นเรื่องปกติครับ ในที่นี้ผม จะขอข้ามวิธีคลี่ไปครับ

จะคลี่ใน Maya หรือ DeepUV ก็แล้วแต่สะดวกครับ ภาพด้านบนนี้คลี่จาก DeepUV ระบายสีใน DeepPaint3D และ import กลับมาที่Maya อีกทีเริ่มทำ Shader ใน Slim ครับ ครั้งแรกทดลองทำ Displacement โดยใช Simple Displacement ของ Slim ก่อน

ต่อ Shading Network ดังภาพ โดยใช Ensemble เป็นตัวรวม ลอง render ดูครับ

เป็นการ Bump แบบเรียบๆ เรื่องจากไม่ได้ติ๊ก Do Displacement ลองทำ Displecement ดูบ้าง

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

อันนี้ผมต่อ Worley เข้ากับ Simple Displacement

ได้ออกมาแบบนี้ครับ เห็นได้ชัดเจนว่ามีการนูนของพื้นผิว โดยไม่ต้องเปลี่ยน model ปัญหาของ Simple Displacement คือไม่สามารถซ้อน Bump ลงไปได ้มาลอง Slim Template ที่เขียนขึ้นมากันดูครับ

xDisplacement สามารถต่อ ภาพเข้าไปได ้สองภาพเพื่อเป็น Displacenment Map และ Bump Map ตามลำดับ

ตั้งค่า Kb0 และ Kb1 ตามความเหมาะสมครับ

render ก็จะออกมาแบบภาพนี้ครับ การใช้งาน Displacement ให้มีประสทธิภาพได ้มีประโยชน์อย่างมากในการสร้างงานด้วย RenderMan เป็นความสามารถที่หาได้ยากใน renderer ตัวอื่น มีSoftware ที่ชื่อ ZBrush สามารถ Paint Displacement แบบ Real-Time ได ้น่าสนใจมากครับ เนื่องจากจะทำให้การสร้าง Displacement Map ง่าย
ขึ้นเยอะทีเดียว จากที่ต้องมานั่ง render ดูเรื่อยๆ ก็สามารถเห็นรูปร่างที่เปลี่ยนไปได้ทันทีที่ทำการ paint ถ้ามีโอกาศ จะเขียนมาเสนออีกครั้งครับ คนที่มใช 3ds max หรือ Maya อาจจะรู้สึกอึดอัดที่จะใช Displacement เนื่องจากมีประสบการณ์ความช้า ในการคำนวณ ลองใช Displacement ใน RAT ดูครับ แล้วจะรูสึกว่า ขาดมันไม่ได้ซะแล้ว

<<Back