ใช้หลายเฉดสี


53

ตอนนี้ฉันกำลังศึกษา opengl shaders แต่ฉันไม่สามารถหาอะไรบางอย่างได้: วิธีการใช้เฉดสีที่แตกต่างกับวัตถุเช่นกาน้ำชาที่แสดงโดยใช้ toon shader และอีกฉากหนึ่งในฉากเดียวกันโดยใช้พื้นผิวที่สะท้อนแสงมาก ฟังก์ชั่นเสียงดังเช่นในวิดีโอนี้

http://www.youtube.com/watch?v=1ogg4ZfdBqU

อีกอันหนึ่งคือการใช้เบลเซอร์เชดในฉากหนึ่งและเบลอการเคลื่อนไหวเบลอภายหลัง ทำอย่างไรถึงจะได้เอฟเฟกต์เหล่านั้นเมื่อคุณสามารถมีเวอร์เท็กซ์ Shader หนึ่งอันและหนึ่งแฟรกเมนต์ Shader ได้? มีเคล็ดลับเช่นการใช้โปรแกรม shader มากกว่าหนึ่งรายการหรือไม่?


เรื่องนาธานและดาวิดคำตอบที่ดีนี้คือเหตุผลที่คุณเห็นคำว่าแสดงผลผ่านหรือShader ผ่าน ; มีหลายรอบที่จำเป็นในการเขียนภาพ / เฟรมสุดท้าย หนึ่งในเหตุผลที่การประมวลผล GPU กลายเป็นสิ่งที่ขนานกันอย่างรวดเร็วและรวดเร็วดังนั้นความต้องการการผ่านหลายครั้งต่อเฟรม กลับไปที่ตัวแสดงซอฟต์แวร์ Quake II หรือ Half Life เพื่อเตือนตัวเองว่าความรักผ่าน shader เพิ่มเข้ากับประสบการณ์กราฟิก 3D ทั้งหมดอย่างไร
วิศวกร

คำตอบ:


59

คำตอบง่ายๆคือคุณเปลี่ยนพวกเขาระหว่างการโทรแต่ละครั้ง ตั้ง shader วาดกาน้ำชาตั้ง shader อื่นวาดกาน้ำชาอื่น

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

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

มีเทคนิคอื่นที่เรียกว่าการแรเงาที่รอการตัดต่อซึ่งคุณสร้างฉากโดยไม่ให้แสงและใช้ในพื้นที่หน้าจอในภายหลัง เป้าหมายหลักคือการลดค่าใช้จ่ายของแสงต่อพิกเซล

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

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

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

ด้วย OpenGL ที่ทันสมัยกว่า (3.0+) คุณจะใช้Framebuffer Objectกับ Renderbuffers Objects เนื่องจาก renderbuffers สามารถปฏิบัติเหมือนพื้นผิว คุณอาจทำสิ่งต่าง ๆ เช่นมี 1 shader render ให้กับ renderbuffers ที่แตกต่างกันหลาย ๆ ตัว (ดังนั้นคุณไม่จำเป็นต้องแสดงเนื้อผ้าของคุณจากนั้นก็จะเป็นบรรทัดฐานของคุณและส่วนประกอบเรืองแสง) แต่การฝึกฝนพื้นฐานยังคงเหมือนเดิม

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


16

คุณเพียงแค่ผูกหนึ่ง shader แสดงวัตถุทั้งหมดโดยใช้ shader นั้นจากนั้นผูก shader ถัดไปแสดงวัตถุโดยใช้หนึ่งนั้น ฯลฯ

คุณสามารถมีวัตถุ shader ได้จำนวนมาก (shader โหลดเข้าสู่หน่วยความจำและรวบรวม) ตามที่คุณต้องการ สามารถผูกได้ครั้งละหนึ่งรายการเท่านั้น (ใช้งานอยู่)


5
ในแง่ของการนำไปใช้ในทุกๆเฟรมฉันใช้ glUseProgram (1) และ glUseProgram (2) เพื่อเปลี่ยนเฉดสี? ประสิทธิภาพราคาแพงแค่ไหน?
ibrabeicker

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

9

การใช้มากกว่าหนึ่ง shader ในฉากนั้นค่อนข้างง่าย เปลี่ยน shader ตั้งค่าสำหรับมันจากนั้นแสดงวัตถุ

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

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

วิธีที่สองเพื่อลดผลกระทบต่อประสิทธิภาพคือการตั้งค่า shader แสดงทุกวัตถุที่ใช้ shader นั้นจากนั้นทำซ้ำ กล่าวอีกนัยหนึ่งคือการแบทช์การแสดงผลของคุณ

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


7

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


4
ต้องใช้ฮาร์ดแวร์ที่มีคุณสมบัติ GL 4.x ซึ่งเป็นฮาร์ดแวร์ระดับ DX11
Nicol Bolas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.