ในระบบวัสดุที่ใช้กราฟฉันจะสนับสนุนประเภทอินพุตและเอาต์พุตที่หลากหลายได้อย่างไร


11

ป้อนคำอธิบายรูปภาพที่นี่

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


พื้นหลัง:

ดังนั้นเมื่อฉันได้ตั้งโปรแกรมระบบการแสดงผล OpenGL อย่างง่ายมาก่อนฉันมักจะสร้างคลาสวัสดุที่โหลดรวบรวมและเชื่อมโยง shaders จากไฟล์ GLSL แบบคงที่ที่ฉันสร้างขึ้นด้วยตนเอง ฉันมักจะสร้างคลาสนี้เป็น wrapper ง่าย ๆ สำหรับการเข้าถึงตัวแปรชุด GLSL เป็นตัวอย่างง่ายๆลองนึกภาพว่าฉันมี Shader Vertex พื้นฐานและ Shader Fragment พื้นฐานพร้อม Texture2D แบบพิเศษสำหรับการส่งผ่านพื้นผิว คลาสวัสดุของฉันเพียงแค่โหลดและรวบรวมสองเฉดสีเหล่านั้นลงในวัสดุและจากจุดนั้นมันจะเปิดเผยอินเทอร์เฟซที่เรียบง่ายสำหรับการอ่าน / เขียนชุด Texture2D ของ shader นั้น

เพื่อให้ระบบนี้มีความยืดหยุ่นเพิ่มขึ้นเล็กน้อยฉันมักจะเขียนด้วยวิธีที่อนุญาตให้ฉันพยายามส่งชุดชื่อ / ประเภทใด ๆ[เช่น: SetUniform_Vec4 ("AmbientColor", colorVec4); ซึ่งจะตั้งค่าเครื่องแบบ AmbientColor เพื่อเวกเตอร์ 4d โดยเฉพาะเรียกว่า "colorVec4" ถ้าชุดที่มีอยู่ในวัสดุ.]

class Material
{
    private:
       int shaderID;
       string vertShaderPath;
       string fragSahderPath;

       void loadShaderFiles(); //load shaders from files at internal paths.
       void buildMaterial(); //link, compile, buffer with OpenGL, etc.      

    public:
        void SetGenericUniform( string uniformName, int param );
        void SetGenericUniform( string uniformName, float param );
        void SetGenericUniform( string uniformName, vec4 param );
        //overrides for various types, etc...

        int GetUniform( string uniformName );
        float GetUniform( string uniformName );
        vec4 GetUniform( string uniformName );
        //etc...

        //ctor, dtor, etc., omitted for clarity..
}

วิธีนี้ใช้งานได้แต่รู้สึกว่าเป็นระบบที่ไม่ดีเนื่องจากลูกค้าของคลาสวัสดุต้องเข้าถึงชุดเครื่องแบบโดยใช้ศรัทธาเพียงอย่างเดียว - ผู้ใช้จะต้องตระหนักถึงชุดเครื่องแบบที่อยู่ในวัตถุแต่ละชิ้นเพราะพวกเขาถูกบังคับให้ ส่งต่อโดยใช้ชื่อ GLSL มันไม่ใช่เรื่องใหญ่โตมากเมื่อมีเพียง 1-2 คนที่ทำงานกับระบบ แต่ฉันไม่สามารถจินตนาการได้ว่าระบบนี้จะขยายได้เป็นอย่างดีเลยและก่อนที่ฉันจะพยายามเขียนโปรแกรมระบบการแสดงผล OpenGL ครั้งต่อไปฉันต้องการระดับ ขึ้นเล็กน้อย


คำถาม:

นั่นคือที่ฉันจนถึงดังนั้นฉันได้พยายามศึกษาวิธีเครื่องมือแสดงผลอื่น ๆ จัดการระบบวัสดุของพวกเขา

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

จากสิ่งที่ฉันสามารถบอกได้การใช้ระบบประเภทนั้นจะง่ายเหมือนคลาส MaterialNode ที่มีคลาสย่อยหลากหลาย (TextureNode, FloatNode, LerpNode ฯลฯ ) แต่ละคลาสย่อย MaterialNode จะมี MaterialConnections

class MaterialConnection
{
    MatNode_Out * fromNode;
    MatNode_In * toNode;
}

class LerpNode : MaterialNode
{
    MatNode_In x;
    MatNode_In y;
    MatNode_In alpha;

    MatNode_Out result;
}

นั่นเป็นแนวคิดพื้นฐานมากแต่ฉันไม่แน่ใจเล็กน้อยเกี่ยวกับวิธีการบางอย่างของระบบนี้ที่จะทำงาน:

1. )หากคุณดู'การแสดงออกของวัสดุ' (โหนด) ต่างๆที่ Unreal Engine 4 ใช้คุณจะเห็นว่าพวกเขาแต่ละคนมีการเชื่อมต่ออินพุทและเอาท์พุทหลากหลายประเภท โหนดบางโหนดลอย, เอาท์พุทบาง vector2, เอาท์พุทเวกเตอร์ 4 บาง, ฯลฯฉันจะปรับปรุงโหนดและการเชื่อมต่อด้านบนเพื่อให้พวกเขาสามารถรองรับประเภทอินพุตและเอาต์พุตที่หลากหลายได้อย่างไร? การทำคลาสย่อย MatNode_Out กับ MatNode_Out_Float และ MatNode_Out_Vec4 (และอื่น ๆ ) เป็นตัวเลือกที่ชาญฉลาดหรือไม่

2. ) ในที่สุดระบบประเภทนี้เกี่ยวข้องกับ GLSL shaders อย่างไร เมื่อดูอีกครั้งที่ UE4 (และคล้ายกันกับระบบอื่น ๆ ที่เชื่อมโยงด้านบน) ผู้ใช้จะต้องเสียบโหนดวัสดุบางส่วนเข้ากับโหนดขนาดใหญ่ด้วยพารามิเตอร์ต่างๆที่แสดงพารามิเตอร์ shader (สีพื้นฐาน, โลหะ, เงา, เปล่งแสง ฯลฯ ) . ข้อสันนิษฐานเดิมของฉันคือ UE4 มีรหัสแบบยาก 'master shader' ที่มีเครื่องแบบหลายแบบและทุกสิ่งที่ผู้ใช้ทำใน 'เนื้อหา' ของพวกเขาจะถูกส่งผ่านไปยัง 'master shader' เมื่อพวกเขาเสียบโหนดเข้ากับ ' โหนดหลัก '

อย่างไรก็ตามเอกสารของ UE4ระบุว่า:

"แต่ละโหนดมีตัวอย่างรหัส HLSL ที่กำหนดให้ทำงานเฉพาะซึ่งหมายความว่าเมื่อคุณสร้างวัสดุคุณกำลังสร้างรหัส HLSL ผ่านการสร้างสคริปต์ด้วยภาพ"

หากเป็นจริงระบบนี้จะสร้างสคริปต์ shader จริงหรือไม่ มันทำงานยังไงกันแน่?


1
เกี่ยวข้องกับคำถามของคุณ: gameangst.com/?p=441
glampert

คำตอบ:


10

ฉันจะพยายามตอบความรู้ที่ดีที่สุดของฉันด้วยความรู้เพียงเล็กน้อยเกี่ยวกับกรณีเฉพาะของ UE4 แต่ใช้เทคนิคทั่วไป

วัสดุกราฟที่ใช้เขียนโปรแกรมได้มากเท่ากับการเขียนโค้ดด้วยตัวเอง มันไม่รู้สึกเหมือนมันสำหรับคนที่ไม่มีพื้นฐานของโค้ดทำให้ดูง่ายขึ้น ดังนั้นเมื่อผู้ออกแบบเชื่อมโยงโหนด "เพิ่ม" เขาก็จะเขียนเพิ่ม (ค่า 1, ค่า 2) และเชื่อมโยงเอาท์พุทกับสิ่งอื่น นี่คือสิ่งที่พวกเขาหมายถึงว่าแต่ละโหนดจะสร้างรหัส HLSL ไม่ว่าจะเป็นการเรียกใช้ฟังก์ชันหรือเพียงแค่คำแนะนำที่ตรงไปตรงมา

ในท้ายที่สุดการใช้กราฟวัสดุก็เหมือนกับการเขียนโปรแกรม shaders ดิบพร้อมห้องสมุดของฟังก์ชั่นที่กำหนดไว้ล่วงหน้าซึ่งทำสิ่งที่มีประโยชน์ทั่วไปและนั่นก็คือสิ่งที่ UE4 ทำ มันมีไลบรารี่ของรหัส shader ที่คอมไพเลอร์ shader จะใช้และฉีดเข้าไปในแหล่งที่มาของ shader สุดท้ายเมื่อมี

ในกรณีของ UE4 ถ้าพวกเขาอ้างว่ามันถูกแปลงเป็น HLSL ฉันคิดว่าพวกเขาใช้เครื่องมือตัวแปลงซึ่งสามารถแปลงรหัส HLSL ไบต์เป็นรหัส GLSL ไบต์ดังนั้นมันจึงใช้งานได้บนแพลตฟอร์ม GL แต่ห้องสมุดอื่น ๆ ก็มีคอมไพเลอร์ shader หลายตัวซึ่งจะอ่านกราฟและสร้างแหล่งภาษาแรเงาที่ต้องการโดยตรง

กราฟวัสดุยังเป็นวิธีที่ดีในการสรุปจากแพลตฟอร์มเฉพาะและมุ่งเน้นไปที่สิ่งที่สำคัญจากมุมมองทิศทางศิลปะ เนื่องจากมันไม่ได้ผูกพันกับภาษาและระดับที่สูงขึ้นมากมันง่ายต่อการปรับให้เหมาะสมสำหรับแพลตฟอร์มเป้าหมายและฉีดโค้ดอื่น ๆ เช่นการจัดการแสงลงใน shader แบบไดนามิก

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

ด้วยวิธีการนี้คุณสามารถกำหนดเขตข้อมูลของโหนดให้เป็น (float | double) และปล่อยให้มันอนุมานชนิดจากการเชื่อมต่อหรือบังคับประเภทให้กับมันโดยไม่ต้องมีลำดับชั้นหรือการเอาชนะ มันขึ้นอยู่กับคุณที่จะออกแบบโครงสร้างข้อมูลกราฟนี้แบบแข็งหรือยืดหยุ่นตามที่คุณต้องการ สิ่งที่คุณต้องมีคือมีข้อมูลเพียงพอเพื่อให้ตัวสร้างโค้ดไม่มีความกำกวมและอาจจัดการสิ่งที่คุณต้องการทำผิด สิ่งสำคัญคือในระดับโครงสร้างข้อมูลพื้นฐานคุณจะต้องมีความยืดหยุ่นและมุ่งเน้นไปที่การแก้ปัญหาในการกำหนดเนื้อหาเพียงอย่างเดียว

เมื่อฉันพูดว่า "กำหนดวัสดุ" ฉันหมายถึงการกำหนดพื้นผิวตาข่ายโดยเฉพาะอย่างยิ่งเกินกว่าสิ่งที่รูปทรงเรขาคณิตให้ ซึ่งรวมถึงการใช้คุณลักษณะจุดสุดยอดเพิ่มเติมเพื่อกำหนดค่ามุมมองของพื้นผิวเพิ่มการกระจัดของมันด้วยความสูง, รบกวนบรรทัดฐานด้วยบรรทัดฐานต่อพิกเซลการเปลี่ยนพารามิเตอร์ตามร่างกายเพื่อเปลี่ยน BRDF และอื่น ๆ คุณไม่ต้องการอธิบายสิ่งอื่นเช่น HDR, tonemapping, ภาพเคลื่อนไหวที่น่าสนใจ, การจัดการแสงหรือสิ่งอื่น ๆ

2) จากนั้นก็ขึ้นอยู่กับตัวกำเนิด shader ของ renderers เพื่อสำรวจโครงสร้างข้อมูลนี้และโดยการอ่านข้อมูลประกอบชุดของตัวแปรและเชื่อมโยงเข้าด้วยกันโดยใช้ฟังก์ชั่น premade และฉีดโค้ดที่คำนวณแสงและเอฟเฟกต์อื่น ๆ เพิ่งทราบว่าเฉดสีไม่เพียง แต่แตกต่างจากกราฟิค API ที่แตกต่างกันเท่านั้น แต่ยังมีความแตกต่างระหว่างตัวเรนเดอร์ที่แตกต่างกัน (การเรนเดอร์ที่เทียบกับไทล์เรนเดอร์ เลเยอร์ระดับต่ำและมุ่งเน้นไปที่การอธิบายพื้นผิวเท่านั้น

สำหรับ UE4 นั้นมีรายการของสิ่งต่าง ๆ สำหรับโหนดสุดท้ายที่คุณพูดถึงซึ่งพวกเขาคิดว่าอธิบายถึง 99% ของพื้นผิวในเกมเก่าและทันสมัย พวกเขาพัฒนาชุดของพารามิเตอร์นี้มานานหลายทศวรรษและพิสูจน์ด้วยจำนวนบ้าของเกมที่เอ็นจิ้นลวงตาได้ผลิตมาจนถึงตอนนี้ ดังนั้นคุณจะสบายดีถ้าคุณทำสิ่งต่าง ๆ เช่นเดียวกับที่ไม่จริง

เมื่อต้องการสรุปให้ละเอียดฉันแนะนำไฟล์. material เพียงเพื่อจัดการกราฟแต่ละอัน ในระหว่างการพัฒนามันอาจจะมีรูปแบบข้อความที่ใช้ในการตรวจแก้จุดบกพร่องและจากนั้นจะได้รับการบรรจุหรือรวบรวมเป็นไบนารีสำหรับการเปิดตัว วัสดุแต่ละรายการจะประกอบด้วยโหนด N และการเชื่อมต่อ N มากเช่นฐานข้อมูล SQL แต่ละโหนดจะมีฟิลด์ N ที่มีชื่อและแฟล็กบางชนิดสำหรับชนิดที่ยอมรับถ้าอินพุตหรือ ouput หากมีการอนุมานประเภท ฯลฯ โครงสร้างข้อมูลรันไทม์เพื่อเก็บวัสดุที่โหลดจะแบนและเรียบง่ายดังนั้น เครื่องมือแก้ไขสามารถปรับเปลี่ยนได้อย่างง่ายดายและบันทึกเป็นไฟล์

จากนั้นปล่อยให้ยกของหนักสำหรับรุ่น shader ขั้นสุดท้ายซึ่งเป็นส่วนที่ยากที่สุดที่จะทำ ส่วนที่สวยงามคือวัสดุของคุณไม่เชื่อเรื่องแพลตฟอร์มการแสดงผลในทางทฤษฎีมันจะทำงานร่วมกับเทคนิคการเรนเดอร์และ API ใด ๆ ตราบใดที่คุณแสดงเนื้อหาในภาษาแรเงาที่เหมาะสม

แจ้งให้เราทราบหากคุณต้องการรายละเอียดเพิ่มเติมหรือการแก้ไขใด ๆ ในคำตอบของฉันฉันสูญเสียภาพรวมของข้อความทั้งหมด


ฉันไม่สามารถขอบคุณมากพอสำหรับการเขียนคำตอบที่ยอดเยี่ยมและประณีต ฉันรู้สึกว่าฉันมีความคิดที่ดีว่าฉันควรไปจากที่นี่! ขอบคุณ!
MrKatSwordfish

1
ไม่มีปัญหากับคู่สนทนาโปรดส่งข้อความถึงฉันหากคุณต้องการความช่วยเหลือเพิ่มเติม จริง ๆ แล้วฉันกำลังทำงานกับสิ่งที่เทียบเท่ากับเครื่องมือของฉันเองดังนั้นหากคุณต้องการแลกเปลี่ยนความคิด ขอให้มีความสุขตอนบ่าย: D
Grimshaw
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.