เป็นไปได้ไหมที่จะสร้างลูกบาศก์ที่มีจุดยอดน้อยกว่า 24 จุด


14

ฉันมีโลกแบบลูกบาศก์เช่น Minecraft และฉันสงสัยว่ามีวิธีการสร้างลูกบาศก์ที่มีจุดยอดน้อยกว่า 24 จุดหรือไม่ดังนั้นฉันจึงสามารถลดการใช้หน่วยความจำได้

ฉันดูเหมือนจะเป็นไปไม่ได้ด้วยเหตุผลสองประการ: บรรทัดฐานจะไม่ออกมาอย่างถูกต้องและพื้นผิวต่อหน้าจะไม่ทำงาน

เป็นกรณีนี้หรือฉันผิด อาจมีเทคโนโลยี DX11 ใหม่แฟนซีที่ช่วยได้บ้าง

แก้ไข: เพื่อชี้แจงฉันมี 2 ข้อกำหนด: ฉันต้องการ normals พื้นผิวสำหรับแต่ละหน้าลูกบาศก์เพื่อให้แสงที่เหมาะสมและฉันต้องการวิธีที่จะระบุดัชนีที่แตกต่างในอาร์เรย์เนื้อสัมผัสสำหรับแต่ละหน้าลูกบาศก์


1
คุณต้องการลดการใช้หน่วยความจำกราฟิกการ์ดหรือการใช้ RAMหรือไม่?
doppelgreener

1
ข้อมูลจุดสุดยอดจะถูกเก็บไว้ใน RAM และ GPU ในตอนนี้ดังนั้นการลดมันจะลดทั้งสองอย่าง
Telanor

คำตอบ:


9

หากคุณต้องการบรรทัดฐานต่อหน้าเท่านั้นและหาก texcoords ของคุณสำหรับใบหน้านั้นเคร่งครัด 0/0, 0/1, 1/0, 1/1 (หรือคล้ายกับรูปแบบของคุณ) คุณสามารถสร้างคิวบ์ได้ 8 verts และทั้ง 30 (แถบที่มีการรีสตาร์ท) หรือดัชนี 36 (รายการ) ดึงข้อมูล normals และ texcoords โดยใช้การค้นหา array คงที่โดยอ้างอิงจาก SV_VertexID ในจุดสุดยอดของคุณ

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

คุณสามารถไปต่อที่ 24 verts ต่อคิวบ์ แต่ยังใช้อินสแตนซ์ แต่ละคิวบ์จะมีขนาดคงที่ในบัฟเฟอร์จุดสุดยอดของคุณ (1x1x1) และคุณจะมีตัวประกอบสเกลและตำแหน่ง (สมมติว่าคิวบ์ของคุณไม่หมุนเมทริกซ์ถ้าเป็นเช่นนั้น) เป็นข้อมูลต่ออินสแตนซ์ ในกรณีที่ไม่หมุนคุณจะต้องเสียค่าใช้จ่าย 24 verts ครั้งเดียว แต่จากนั้นแต่ละคิวบ์ต้องการเพียง 6 ลอยเพื่อระบุอย่างเต็มที่ ในกรณีหมุนคุณดูที่ 16 ลอย แต่แม้จะประหยัดมาก (คุณมีแนวโน้มที่จะคอขวดด้าน CPU ในเมทริกซ์แปลงในกรณีนี้ - สำหรับกรณีที่ไม่หมุนสร้างเมทริกซ์ได้ทันที จุดสุดยอดของคุณ shader - แม้ว่ามันจะทำต่อจุดสุดยอดอย่างรวดเร็วอย่างโง่เขลาที่คุณไม่จำเป็นต้องกังวลเกี่ยวกับมัน)

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

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

ฉันใช้รหัสเบนช์มาร์กในเอนจินของฉันที่เพิ่งวาดกลุ่มก้อนโดยใช้วิธีนี้และฉันสามารถเคี้ยวได้มากกว่า 300,000 ลูกในขณะที่ยังคงทำการล้าง 60fps บน GPU ที่ค่อนข้างต่ำและไม่ทำอะไรเลยเพื่อเพิ่มประสิทธิภาพของกระบวนการ . เป็นที่ยอมรับว่าฉันไม่ใช่แสงหรือการทำพื้นผิว แต่ฉันมีการเปิดใช้งานการผสมอัลฟา backface การเลือกสรรการปิดการใช้งานและโดยรวมมันสมดุลกับส่วนของฉัน "ไม่ทำอย่างอื่นเพื่อเพิ่มประสิทธิภาพ" ดังนั้นจึงควรให้ความคิดที่เหมาะสม ballpark คุณสามารถตีด้วยวิธีนี้


1
ฉันใช้อินสแตนซ์ก่อนหน้านี้และใช้งานได้ดีกับลูกน้อยกว่า 40k คิว แต่ฉันมีอย่างน้อย 256k คิวบ์และการอินสแตนซ์ก็ไม่ได้จัดการเช่นกัน การใช้ SV_VertexID พร้อมกับการค้นหานั้นถือว่าเป็นสัญญาที่ดีมาก
Telanor

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

นอกจากนี้การรักษาจำนวนแผนที่ให้ต่ำก็เป็นสิ่งจำเป็นเช่นกัน แม็พ / เขียนหนึ่งคิวบ์ / unmap 40k ครั้งจะช้ากว่าแผนที่ / เขียน 40k คิวบ์ / unmap เพียงครั้งเดียว หากคุณกำลังทำแบบเดิมลองเปลี่ยนไปใช้แบบหลัง
Maximus Minimus

15

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

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

ภาพด้านล่างแสดงให้เห็นถึงแนวคิดนี้ แต่ในรูปแบบ 2D เพื่อความเข้าใจที่ง่ายขึ้น ในภาพมี 11 บล็อกที่ถูกครอบครอง (แสดงโดยวงกลมสีเทาที่เต็มไป) ซึ่งโดยปกติจะต้องการ 4 x 11 = 44 ขอบเพื่อแทน (4 เพราะมันเป็นสี่เหลี่ยมไม่ใช่ลูกบาศก์) แต่อย่างที่คุณเห็นคุณจะต้องวาดเส้นขอบเมื่อพวกมันสัมผัสกับสี่เหลี่ยมจัตุรัสที่ว่างเปล่าซึ่งในกรณีนี้คือ 8 ขอบเท่านั้น

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

หากตัวอย่างง่ายๆใน 2D สามารถจัดการลด 44 edge เป็น 8 edge ให้จินตนาการถึงกำไรในโลก 3 มิติขนาดใหญ่ ...

นี่คือวิธีการที่อธิบายไว้ในบทความนี้ซึ่งฉันแนะนำให้คุณอ่านแม้ว่าจะเป็นเป้าหมายของ OpenGL แนวคิดควรเป็นสากลแม้ว่า

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


1
บทความที่น่าสนใจมาก ฉันกำลังทำการปรับขอบให้เหมาะสมอยู่แล้วซึ่งแน่นอนว่าช่วยได้มาก ฉันจะลองทำเฉดเรขาคณิตแล้วลองดูว่ามันใช้ได้หรือเปล่า
Telanor

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

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

ถ้าเป็นประสิทธิภาพที่คุณต้องการอย่าใช้รูปทรงเรขาคณิต ... เกือบจะตลอดไป พวกเขาขันท่อจนหมด หากคุณต้องการสร้างรูปทรงเรขาคณิตบน GPU ให้ใช้ตัวประมวลผลร่วมหรือ openCL
Robert Fraser
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.