Unity ให้ความช่วยเหลือมากมายแก่นักพัฒนาเกมซึ่งรวมถึงการเสนอ Shaders เพื่อให้ VFX และภาพเคลื่อนไหวที่ซับซ้อนง่ายขึ้น คุณสามารถไปได้ไกลโดยการแปรงด้วย Shaders มาตรฐานที่มาพร้อมกับ Unity อย่างไรก็ตามคุณสามารถปรับปรุงภาพของโครงการของคุณโดยการเขียนเฉดสีแบบกำหนดเอง Show
ในบทช่วยสอนนี้คุณจะได้เรียนรู้:
ในการฝึกฝนให้ขัดกราฟิกเป็นฉากทะเลทรายด้วยเฉดสีที่กำหนดเอง ดาวน์โหลดไฟล์โครงการโดยคลิกที่ปุ่ม ดาวน์โหลดวัสดุ ที่ด้านบนหรือด้านล่างของบทช่วยสอนนี้ โครงการตัวอย่างมีโมเดลและพื้นผิวเพื่อให้คุณสามารถมีสมาธิกับ Shaders โครงการตัวอย่างใช้ Unity 2019.3 แม้ว่าทุกอย่างในบทช่วยสอนนี้จะทำงานในเวอร์ชันที่เก่ากว่า หมายเหตุ : นี่คือบทช่วยสอนระดับกลางที่สมมติว่าคุณทราบพื้นฐานของการใช้ Unity แล้ว หากคุณไม่คุ้นเคยกับ Unity คุณสามารถเริ่มต้นด้วย Introduction to Unity ของเรา: บทแนะนำการเริ่มต้นใช้งาน Shaders คืออะไรคอมพิวเตอร์กราฟิกโดยเฉพาะกราฟิก 3D ใช้ข้อมูลหลายประเภทเพื่อสร้างภาพ: มาสก์, พื้นผิว, ไฟและอื่น ๆ ข้อมูลนี้จะถูกถ่ายโอนไปยังฮาร์ดแวร์กราฟิกซึ่งจะประมวลผลภาพและแสดงบนหน้าจอ การเรนเดอร์ คือสิ่งที่โปรแกรมเมอร์เรียกกระบวนการสร้างภาพและ Shader's เป็นโปรแกรมสั้น ๆ ที่แสดงข้อมูลกราฟิก นั่นคือ Shader เป็นโปรแกรมที่ใช้มาสก์พื้นผิว ฯลฯ เป็นอินพุตและสร้างรูปภาพเป็นเอาต์พุต การทำความเข้าใจประเภทของ Shadersในทางเทคนิคคน Shader ไม่ได้สร้างภาพ ทั้งหมด และไม่มี ค่อนข้างมีความแตกต่างหลากหลายประเภทที่ทำสิ่งต่าง ๆ ประเภทหลักคือ Pixel Shader ตั้งชื่อเพื่อเหตุผลที่ชัดเจนว่ามันส่งเสียงพิกเซล คำศัพท์ทั่วไปอีกคำหนึ่งคือ Fragment Shader เนื่องจากแต่ละพิกเซลเป็นส่วนของภาพทั้งหมด Fragment Shaders ปล่อยสีพิกเซลเดียวซึ่งจะคำนวณตามตำแหน่งของพิกเซลในรูปหลายเหลี่ยม โปรแกรมรันซ้ำไปซ้ำมาส่วนใหญ่ขนานกันเพื่อสร้างพิกเซลทั้งหมดของรูปหลายเหลี่ยมทั้งหมดที่ประมวลผลโดย Shader ความสามารถในการประมวลผลหลายพิกเซลในเวลาเดียวกันเป็นส่วนสำคัญของวิธีที่การ์ดวิดีโอเร่งกราฟิก นอกจากนี้ยังมี Vertex Shaders ที่คุณใช้ในการคำนวณตำแหน่งของจุดยอดในภาพ ในขณะที่อินพุตอยู่ในสามมิติคอมพิวเตอร์จำเป็นต้องกำหนดว่าจุดยอดปรากฏในสองมิติก่อนที่จะสามารถแสดงพิกเซล คุณสามารถบรรลุเอฟเฟ็กต์ภาพที่น่าสนใจได้ด้วยการจัดการเอาต์พุตข้อมูล Vertex Shaders แต่คุณจะไม่ครอบคลุมในบทช่วยสอนนี้ Compute Shaders ไม่ได้แสดงผลอะไรเลย แต่เป็นเพียงซอฟต์แวร์ที่ทำงานบนฮาร์ดแวร์วิดีโอ Shaders เหล่านี้เป็นนวัตกรรมล่าสุด – ฮาร์ดแวร์วิดีโอรุ่นเก่าอาจไม่สนับสนุน เช่นเดียวกับ Fragment และ Vertex Shader Compute Shader เป็นโปรแกรมสั้น ๆ ที่รันการ์ดกราฟิกในแบบขนานอย่างหนาแน่น Compute Shaders ไม่เหมือนกับภาพอื่น ๆ แต่พวกเขาได้รับประโยชน์จากการประมวลผลวิดีโอการ์ดแบบขนานเพื่อทำสิ่งต่าง ๆ เช่นการขุด cryptocurrency คุณจะไม่ทำงานกับ Compute Shaders ในบทช่วยสอนนี้ Unity แนะนำ Shader อีกประเภทหนึ่ง, Surface Shader นี่คือ Shaders ที่ทำการคำนวณแสงสำหรับคุณและคุณเพียงแค่ต้องเขียนโค้ด – จำไว้ว่าโปรแกรม Shader คือ โปรแกรม – เพื่อจัดการคุณสมบัติพื้นผิวอื่น ๆ เช่นสีและพื้นผิว Surface Shaders เป็นชิ้นส่วนและ Vertex Shaders ภายใต้ประทุน แต่ Unity สร้างรหัสเพื่อจัดการกับแสง สิ่งนี้มีประโยชน์เนื่องจากการคำนวณแสงมีความซับซ้อนมากและมักจะเป็นมาตรฐานระหว่างเฉดสีที่แตกต่างกันมากมาย ในที่สุดข้อมูลกราฟิกบอกการ์ดว่า Shader จะใช้ผ่านวัสดุ เมื่อตรวจสอบวัสดุคุณจะสังเกตเห็นเมนูที่ด้านบน เมนูนั้นจะเลือก Shader ที่จะกำหนดให้กับวัสดุนั้น ดังนั้นเมื่อฮาร์ดแวร์กราฟิกทำซ้ำรูปหลายเหลี่ยมมันจะเรียกใช้ส่วนที่เป็นเงาของวัสดุของรูปหลายเหลี่ยม ตกลงคำอธิบายที่เพียงพอ ได้เวลาเขียน Shaders แล้ว! การเขียน Shader ที่กำหนดเองหากคุณยังไม่ได้เปิดโครงการเริ่มต้นจากนั้นเปิด RW / Scenes / SampleScene คุณจะเห็นฉากเกาะทะเลทรายที่ออกแบบไว้ล่วงหน้าพร้อมด้วยนางแบบตำแหน่งที่มีวัสดุที่กำหนดให้ ฉากที่มีอยู่ไม่ได้ดู น่ากลัว แต่คุณสามารถปรับปรุงได้อย่างน้อยสองวิธี: เกาะมีความแข็งขอบสี่เหลี่ยมและน้ำนิ่ง . คุณสามารถแก้ปัญหาทั้งสองด้วย Custom Shaders อย่างไรก็ตามก่อนที่จะแก้ไขปัญหาเหล่านี้คุณต้องเข้าใจวิธีการสร้าง Shaders ในการเริ่มต้นสร้างทรัพยากร Surface Shader ในโฟลเดอร์ Shaders โดยการคลิกขวาและเลือก สร้าง▸ Shader Surface Shader พื้นผิวมาตรฐาน ตั้งชื่อมัน MyFirstShader ไปที่โฟลเดอร์ วัสดุ เลือก การ์ตูนทราย และคลิกที่เมนู Shader ที่ด้านบนของ ผู้ตรวจการ เลือก กำหนดเอง▸ MyFirstShader เพื่อเปลี่ยนวัสดุเป็น Shader ยังไม่มีอะไรเปลี่ยนแปลงในฉากเพราะคุณยังไม่ได้เปลี่ยนรหัส Shader มาตรฐานใด ๆ อย่างไรก็ตามวัสดุทรายบนเกาะของคุณใช้ Shader ที่กำหนดเองแทน Shader มาตรฐานที่สร้างไว้ในอุปกรณ์ การดูเทมเพลตเริ่มต้นสำหรับ Custom Shaderดับเบิลคลิกที่เนื้อหา Shader เพื่อเปิดในเครื่องมือแก้ไขรหัส และตรวจสอบรหัส Shader ประกอบด้วยส่วนต่าง ๆ ภายในขอบหลัก SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2005 รหัสทั้งหมดอยู่ในบล็อก shader ที่มีวงเล็บปีกกาชื่อ กำหนดเอง / MyFirstShader สิ่งนี้จะบอก Unity ว่าจะแสดงอะไรเมื่อเรียกดูเมนู Shader ในวัสดุ ดูที่ส่วนต่างๆ … Propertiesคุณสมบัติ { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", range (0.1)) = 0.5 _Metallic ("โลหะ", ช่วง (0.1)) = 0.0 } บล็อก SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2006 ที่ด้านบนคือที่ซึ่งคุณประกาศคุณสมบัติที่ผู้ใช้กำหนดแตกต่างกัน เหล่านี้คือค่าที่คุณสามารถแก้ไขในการตรวจสอบเมื่อเลือกวัสดุ ดูรายละเอียดในบรรทัดเดียว: อันดับแรกคุณจะเห็นชื่อตัวแปรที่ใช้ในรหัส จากนั้นในวงเล็บให้กำหนดชื่อที่คุณต้องการแสดงในตัวตรวจสอบ นอกจากนี้ในวงเล็บคุณยังประกาศประเภทของคุณสมบัติ: สีพื้นผิว 2D หรือช่วงตัวเลข ในที่สุดหลังจาก SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2007 คุณให้ค่าคุณสมบัติเป็นค่าเริ่มต้น บล็อก SubShaderSubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 200 SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2008 เป็นรหัสที่ส่วนใหญ่ของรหัส Shader จะไป สองบรรทัดแรกของบล็อกนี้ประกาศรหัสการระบุที่ยอมรับโดย Unity และระบุค่าที่ใช้โดยระบบ Level-of-Detail (LOD) ของ Unity ในกรณีนี้การระบุแท็กประกาศว่า Shader ไม่โปร่งใส ในทางเทคนิคอาจมีบล็อคย่อยหลายช่วง แต่คุณไม่ได้เข้าสู่ระดับความซับซ้อนในบทช่วยสอนนี้ บล็อก CGPROGRAMCGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.0 บรรทัดเหล่านี้ประกาศหน้าที่สำคัญหลายประการของโค้ดที่ต้องติดตาม ก่อนอื่นพวกเขาระบุว่ารหัสต่อไปนี้ใช้ภาษา Cg มีภาษาการเขียนโปรแกรมต่าง ๆ สำหรับการเขียน Shaders ทุกอย่างจนถึงจุดนี้ใช้ภาษาของ Unity นั่นคือ ShaderLab ในขณะเดียวกันคำสั่ง SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2009 ตั้งค่าการกำหนดค่า ในรายละเอียดครั้งแรก: พื้นผิว บอกคอมไพเลอร์ Shader ว่านี่คือ Surface Shader จำไว้ว่าประเภทอื่น ๆ ได้แก่ Fragment และ Vertex Shaders CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.00 เป็นชื่อของคุณสมบัติหน้าจอหลักด้านล่าง CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.01 ประกาศว่าคุณต้องการไฟรุ่นใด – ไฟรุ่นอื่นรวมถึง Lambert และ Blinn-Phong แต่แสงที่มีพื้นฐานมาจากร่างกายนั้นดีที่สุด CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.02 เปิดใช้งานการแรเงาแบบไดนามิกสำหรับ Shader นี้ ตัวแปรคุณสมบัติ MainTexsampler2D _MainTex; สิ่งนี้ประกาศตัวแปรที่สอดคล้องกับคุณสมบัติอย่างใดอย่างหนึ่ง แม้ว่ามันดูเหมือนจะซ้ำซ้อนเล็กน้อย แต่คุณต้องประกาศตัวแปรที่นี่เพื่อให้โค้ด Cg ใช้คุณสมบัตินั้น ตัวแปรเหล่านี้สามารถเป็นหนึ่งในหลาย ๆ ประเภทรวมทั้ง CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.03 สำหรับรูปภาพพื้นผิวและ CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.04 / CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.05 / CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.06 ค่าตัวเลขสามารถมีหมายเลขต่อท้ายเพื่อสร้างเวกเตอร์ ตัวอย่างเช่น CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.07 หมายถึงตัวเลขสี่ตัว คุณสามารถเข้าถึงค่าในเวกเตอร์ด้วยคุณสมบัติ. xyzw หรือ. rgba ตัวอย่างเช่น CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.08 ในรหัส Shader ดึงตัวเลขสามตัวแรกจาก CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.07 เรียกว่า sampler2D _MainTex;0 คุณต้องประกาศคุณสมบัติทั้งหมดเป็นตัวแปรในรหัส Cg คุณสามารถดูชื่อคุณสมบัติอื่น ๆ ได้ในภายหลังในบทช่วยสอน เหตุใดรหัสของ Unity จึงแยกออกจากกันเมื่อเทียบกับรายการเดียวมันเป็นปริศนา แต่มันไม่สำคัญ อินพุตและตัวแปรแอตทริบิวต์struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ) บล็อกรหัสนี้ประกาศโครงสร้างข้อมูลที่เรียกว่า sampler2D _MainTex;1 และแสดงค่าในนั้น ค่าอินพุตเฉพาะในโค้ดเทมเพลตคือพิกัด UV ของพื้นผิวหลัก แต่มีค่าอินพุตหลายค่าที่ Shaders สามารถเข้าถึงได้ ข้อมูลกราฟิกจะให้ค่าอินพุตที่คุณประกาศที่นี่กับ Shader ฟังก์ชั่นหน้าจอหลักการเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.00 เป็นคุณสมบัติเงาที่สำคัญที่สุดซึ่งคุณได้ประกาศไว้ในบรรทัด SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2009 ด้านบน พารามิเตอร์แรกคือโครงสร้าง sampler2D _MainTex;1 ในขณะที่พารามิเตอร์ที่สองคือเอาต์พุตที่ฟังก์ชันเขียน คุณจะสังเกตเห็นว่าโครงสร้างเอาต์พุตมีพารามิเตอร์เช่น sampler2D _MainTex;5 และ sampler2D _MainTex;6 ที่คุณระบุโดยใช้คุณสมบัติ Shader หนึ่งบรรทัดใน sampler2D _MainTex;7 ซึ่งไม่ใช่การกำหนดหมายเลขอินพุตที่เหมาะสมให้กับค่าเอาต์พุตคือ sampler2D _MainTex;8 หน่วยอนุญาต sampler2D _MainTex;9 เพื่อค้นหาสีของพื้นผิวในพิกัดที่กำหนด เมื่อเขียน Fragment Shader คุณต้องรวมไลบรารี Shader ของ Unity ไว้อย่างชัดเจน แต่ Surface Shaders จะรวมไลบรารีโดยอัตโนมัติ FallBack shaderFallBack "กระจาย" } หลังจากรหัส Cg คุณประกาศ shader ทางเลือกแม้ว่าจะไม่จำเป็นก็ตาม สิ่งนี้ต้องใช้ Unity เพื่อใช้ตัวเลือกสำรองหากฮาร์ดแวร์กราฟิกไม่สามารถเรียกใช้หน้าจอย่อยแบบกำหนดเองใด ๆ ได้เนื่องจากโดยทั่วไปแล้วจะเป็นการ์ดกราฟิกรุ่นเก่าที่ไม่รองรับคุณสมบัติของตัวปรับภาพ ตกลงตอนนี้คุณเข้าใจโครงสร้างของรหัส Shader แล้วถึงเวลาที่ต้องจัดการกับปัญหาด้านภาพที่ระบุไว้ในตอนต้นของส่วนนี้ การเพิ่มสี Vertex ลงบนหน้าจอ Surfaceปัญหาแรกที่คุณต้องการแก้ไขในฉากคือเกาะมีขอบแข็งและเหลี่ยม คุณสามารถเห็นขอบของเว็บได้ชัดเจนในขณะนี้ แต่ชายหาดที่แท้จริงดูเหมือนจะจางหายไปตามสีของน้ำ มีหลายวิธีที่จะทำให้ลุคนี้เป็นเกม แต่วิธีง่าย ๆ ใช้ สียอดนิยม เพื่อทำความเข้าใจว่าสีจุดสุดยอดคืออะไรคุณต้องตระหนักว่า "จุดสุดยอด" เป็นเพียงชุดข้อมูล ข้อมูลนี้มีจุดสูงสุดเสมอ แต่คุณสามารถรวมตัวเลือกได้หลายตัว พิกัดของพื้นผิวเป็นส่วนที่เพิ่มขึ้นโดยทั่วไปด้วยพิกัด (ระบุด้วยตัวอักษร UV แทนที่จะเป็น XY) ให้ตัวเลขที่คุณใช้เมื่อทำงานกับพื้นผิว สีเป็นอีกทางเลือกหนึ่งโดยให้หมายเลขที่คุณใช้เมื่อคำนวณเอาท์พุทสีของ Shader ตัวอย่างเช่นหากคุณกำหนดจุดสุดยอดเป็นสีแดงรูปหลายเหลี่ยมที่ใช้จุดสุดยอดนั้นจะมีสีแดง นอกจากนี้หากจุดยอดของรูปหลายเหลี่ยมมีสีที่ต่างกันสีเหล่านี้จะถูกแทรกเข้าไปทั่วใบหน้าของรูปหลายเหลี่ยม ตานี้ได้กำหนดสีเอเพ็กซ์แล้ว แต่คุณไม่สามารถมองเห็นได้เพราะ Shader มาตรฐานของ Unity ไม่สามารถใช้สีเอเพ็กซ์ได้ โดยเฉพาะยอดเขาด้านล่างน้ำมีสีเข้มกว่าในขณะที่ยอดเขาที่เหลืออยู่บนเกาะเป็นสีขาว สีเหล่านี้จะสร้างการไล่ระดับสีที่สะดวกสบายตามแนวชายหาดถ้ามองเห็นได้ดังนั้นงานต่อไปของคุณคือการเขียน shader แบบกำหนดเองที่จัดการกับสีด้านบน การสร้าง Shader แบบกำหนดเองสำหรับสี Vertexสร้าง Surface Shader ใหม่และตั้งชื่อ LitVertexColor ป้อนเนื้อหาการ์ตูน ทราย เพื่อใช้ Shader นี้จากนั้นเปิดเนื้อหาของ Shader เพื่อแก้ไขรหัส คุณเพียงแค่ทำการเพิ่มสองส่วนเล็ก ๆ สำหรับสีของจุดยอด ขั้นแรกเพิ่มรหัสต่อไปนี้ลงใน sampler2D _MainTex;1 struct: struct อินพุต { float2 uv_MainTex; float4 vcolor: สี; // จุดสุดยอดสี }; จากนั้นรวม struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)1 ในการคำนวณสีที่เกิดขึ้นใน CGPROGRAM บล็อก // รูปแบบการส่องสว่างตามมาตรฐานทางกายภาพ // และเปิดใช้งานเงาในแสงทุกประเภท #pragma surface surf เงาแบบเต็มมาตรฐาน // ใช้เป้าหมาย Shader Model 3.0 เพื่อให้ได้แสงที่ดีกว่า # pragma เป้าหมาย 3.00: : fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color * IN.vc_MainTex และนั่นแหล่ะ! บันทึก Shader และกลับสู่ฉาก Unity เมื่อ Shader รวมตัวกันคุณจะเห็นขอบเกาะกลมกลืนไปกับน้ำ แอนิเมชันของพื้นผิวน้ำตอนนี้ทรายดูน่าดึงดูดยิ่งขึ้น! ในระหว่างนี้ปัญหาที่สองที่คุณระบุคือน้ำนิ่งสนิท คุณสามารถเปลี่ยนได้ด้วย shader ที่กำหนดเองอื่นแม้ว่าคุณจะไม่ต้องการให้แสงในครั้งนี้ โปรดจำไว้ว่า Surface Shaders จัดการแสงให้กับคุณดังนั้นคุณจะไม่สร้าง Surface Shader ในครั้งนี้ สร้าง Shader ที่ไม่ส่องสว่างแต่ให้สร้าง Shader ที่ไม่มีแสงสว่าง ผ่านเมนูคลิกขวา: สร้าง▸ Shader ▸ Unlit Shader มอบเนื้อหาใหม่ของ Shader CartoonWater และเปิดในเครื่องมือแก้ไขรหัสของคุณ อันแรกเป็นอันแรกอัพเดตชื่อของ shader ที่ด้านบน Shader "Custom / CartoonWater" ชื่อเริ่มต้นสำหรับ Shader นี้คือ struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)3 การเปลี่ยนชื่อเป็น struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)4 ช่วยให้ค้นหา Shaders ที่คุณกำหนดเองได้ง่ายขึ้นในเมนู จากนั้นเพิ่มคุณสมบัติเพิ่มเติมบางอย่างลงใน water shader ของคุณ บล็อก struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)5 บล็อกควรมีลักษณะเช่นนี้: คุณสมบัติ { _MainTex ("พื้นผิว", 2D) = "white" {} _Opacity ("Opacity", ช่วง (0.1)) = 0.5 _AnimSpeedX ("ความเร็วภาพเคลื่อนไหว (X)", ช่วง (0.4)) = 1.3 _AnimSpeedY ("ความเร็วการเคลื่อนไหว (Y)", ช่วง (0.4)) = 2.7 _AnimScale ("Anim Scale", ช่วง (0.1)) = 0.03 _AnimTiling ("Anim Tiling", ช่วง (0.20)) = 8 } Unlit Shader มาตรฐานมีเพียงคุณสมบัติพื้นผิวเดียว struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)6 ดังนั้นคุณจึงเพิ่มคุณสมบัติหลายประการเพื่อควบคุมความทึบของน้ำและโครงสร้างพื้นผิวเคลื่อนไหวอย่างไร อัปเดตส่วนแท็กถัดไปและหลังบรรทัด struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)7 เพิ่มตัวเลือกใหม่: SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2000 แท็กมาตรฐานคาดว่าจะมีวัสดุทึบแสงดังนั้นคุณจึงเพิ่มและปรับค่าสถานะบางอย่างเพื่อสนับสนุนความโปร่งใส โปรดระวังเป็นพิเศษว่าการปิด struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)8 หมายความว่าน้ำจะไม่ซ่อนวัตถุอื่น ๆ ในบัฟเฟอร์ความลึกในขณะที่คุณตั้งค่า struct อินพุต { float2 uv_MainTex; }; _Glossiness ครึ่งหนึ่ง _metallic ครึ่ง solid4 _Color; // เพิ่มการรองรับอินสแตนซ์สำหรับ Shader นี้ คุณต้องตรวจสอบ // & # 39; เปิดใช้งานอินสแตนซ์ & # 39; บนวัสดุที่ใช้ Shader // ดู https://docs.unity3d.com/Manual/GPUInstancing.html สำหรับ // ข้อมูลเพิ่มเติมเกี่ยวกับอินสแตนซ์ // #pragma instancing_options ใช้การปรับขนาดแบบสม่ำเสมอ UNITY_INSTANCING_BUFFER_START (คุณสมบัติ) // เพิ่มคุณสมบัติเพิ่มเติมสำหรับแต่ละอินสแตนซ์ที่นี่ UNITY_INSTANCING_BUFFER_END (คุณสมบัติ)9 เพื่อใช้ค่าอัลฟา ตอนนี้ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }0 ด้วยชุด การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }1 คุณเคยทำงานกับ Surface Shader แต่ตอนนี้คุณกำลังจัดการกับ Vertex และ Fragment Shader ตอนนี้ ดังนั้นในขณะที่ SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2009 คำสั่งประกาศฟังก์ชั่นเงาพื้นผิวก่อนหน้านี้คราวนี้ SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2009 คำสั่งประกาศฟังก์ชัน Vertex และ Fragment Shading นอกจากนี้ยังสังเกตคำสั่ง การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }4 Unity เสนอไลบรารี่ของคุณสมบัติที่มีประโยชน์ที่นี่ (ซึ่งบรรทัดนี้นำเข้าเพื่อใช้ใน shader) พวกเขาทำสิ่งที่มีประโยชน์เช่นลองพื้นผิวและติดตามเวลา Surface Shaders จะได้รับไดเรกทอรีเหล่านี้โดยอัตโนมัติเมื่อคุณสร้างรหัส แต่จะต้องรวมไว้ใน Vertex และ Fragment Shader อย่างชัดเจน Unity's UnityCG.cginc รวมเอาตัวแปรที่กำหนดไว้ล่วงหน้าและฟังก์ชั่นผู้ช่วย ตอนนี้ดูโครงสร้างที่รวม: SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2001 มีโครงสร้างอินพุตสองแบบในเวลานี้แทนที่จะเป็นโครงสร้างอินพุตเดียวสำหรับ Surface Shader คุณป้อนโครงสร้างแรกของ Vertex Shader ซึ่งจะปล่อยโครงสร้างที่สอง งานพิมพ์นี้จาก Vertex Shader จากนั้นไปที่ทางเข้า Fragment Shader ขวาภายใต้ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }5 บรรทัดในรหัส Cg หลักเพิ่มคุณสมบัติใหม่ดังต่อไปนี้: SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2002 เช่นเดียวกับใน Surface Shader ก่อนหน้าคุณต้องประกาศคุณสมบัติทั้งหมดเป็นตัวแปรในรหัส Cg คุณจะใช้คุณสมบัติเหล่านี้เพื่อเปลี่ยนพื้นผิวและทำให้เคลื่อนไหวในคุณสมบัติเงาหลัก ตอนนี้ในคุณลักษณะการขนส่งหลักของ Shader ที่ด้านบน (เหนือ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }6 ความคิดเห็นเกี่ยวกับโค้ดเพิ่ม: SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2003 โค้ดสองบรรทัดนี้เป็นเนื้อของเอฟเฟกต์น้ำแบบเคลื่อนไหว รหัสนี้ชดเชยค่าพิกัด UV ที่ได้รับพร้อมกับปริมาณการเปลี่ยนตำแหน่งเมื่อเวลาผ่านไป ผลลัพธ์ที่ได้คือภาพเคลื่อนไหวที่หมุนวนของพื้นผิว ในขณะเดียวกันโค้ดทั้งสองนั้นก็เหมือนกัน แต่ในทิศทางที่ต่างกัน คุณจะเข้าใจทั้งสองอย่างหลังจากแยกรายละเอียดออกมา อันดับแรกโค้ดเรียกฟังก์ชันตรีโกณมิติไม่ว่าจะเป็นไซน์หรือโคไซน์เพื่อที่ค่าจะแตกต่างกันไปตามคลื่นซ้ำ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }7 ชั่งจำนวนที่ระบุ ตามที่ชื่อแนะนำ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }7 ควบคุมการเรียงลำดับของเอฟเฟกต์ - ในกรณีนี้โดยส่งผลกระทบต่อความถี่ของคลื่นไซน์ ถัดไปเพิ่มเวลาไปยังหมายเลขที่ป้อนและรับค่าส่งคืนเพื่อเลื่อนไปตามคลื่นไซน์เมื่อเวลาผ่านไป รหัสห้องสมุดจากอดีตรวมถึงตัวแปรที่ติดตามเวลา การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }9 เป็นเวกเตอร์ของตัวเลขสี่ตัวซึ่งค่าสี่ค่านั้นถูกลดขนาดโดยปริมาณที่แตกต่างกันเพื่อความเรียบง่าย นั่นคือสาเหตุที่รหัสใช้ FallBack "กระจาย" }0 และไม่ใช่แค่ การเล่นเซิร์ฟว่าง (อินพุตเข้า, ออกจากพื้นผิวเอาท์พุทมาตรฐานมาตรฐาน o) { // Albedo มาจากพื้นผิวที่กระชับกับสี fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // เมทัลลิกและสมดุลมาจากตัวแปรสไลเดอร์ o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG }9; FallBack "กระจาย" }2 เป็นตัวเลขที่สองในเวกเตอร์ ในที่สุดคุณก็คูณทุกสิ่งด้วย FallBack "กระจาย" }3 คุณสมบัติที่ควบคุมประสิทธิภาพของเอฟเฟกต์ ขนาดใหญ่ขึ้นหมายถึงคลื่นมากขึ้น ในที่สุดเหนือ FallBack "กระจาย" }4 รหัสบรรทัดในฟังก์ชั่น FallBack "กระจาย" }5 เพิ่ม: SubShader { แท็ก {"RenderType" = "ทึบแสง"} LOD 2004 ที่นี่รหัสจะตั้งค่าอัลฟาของคุณสมบัติ FallBack "กระจาย" }6 อย่าลืมทำเช่นนี้ หลังจาก สุ่มตัวอย่างเนื้อสัมผัส มิฉะนั้นพื้นผิวจะเขียนทับค่าอัลฟา ] ในมุมมอง เกม เมื่อคุณกด เล่น จะไปที่ไหนจากที่นี่?ดาวน์โหลดไฟล์โครงการที่สมบูรณ์โดยคลิกที่ปุ่ม วัสดุดาวน์โหลด ที่ด้านบนหรือด้านล่างของบทช่วยสอนนี้ ตอนนี้คุณรู้พื้นฐานของการเขียน Shaders ที่กำหนดเองใน Unity! มีอะไรอีกมากมายให้เรียนรู้และทรัพยากรที่ดีในการอ่านคือคู่มือ Shader ของ Unity โปรดจำไว้ว่าคุณสมบัติที่ใช้งานสะดวกที่คุณเคยใช้มาก่อนหรือไม่ ถ้าคุณอยากรู้เกี่ยวกับคุณสมบัติของผู้ช่วยเหลือที่มีอยู่คุณสามารถตรวจสอบได้จากที่นี่ หากคุณสนใจที่จะเรียนรู้เกี่ยวกับการแรเงาด้วย Unity ให้ดูที่บทช่วยสอนอื่น ๆ บนกราฟ Shader ของ Unity ที่นี่ ฉันหวังว่าคุณจะสนุกกับการสอนนี้! หากคุณมีคำถามความคิดเห็นหรือข้อเสนอแนะอย่าลังเลที่จะออกจากพวกเขาในความคิดเห็นด้านล่างหรือเยี่ยมชมฟอรั่มของเรา raywenderlich.com รายสัปดาห์จดหมายข่าว raywenderlich.com เป็นวิธีที่ง่ายที่สุดในการติดตามข้อมูลทุกสิ่งที่คุณจำเป็นต้องรู้ในฐานะนักพัฒนามือถือ |