สำหรับการเรนเดอร์ voxel จะมีประสิทธิภาพมากขึ้น: VBO ที่สร้างไว้ล่วงหน้าหรือ shader เรขาคณิต


26

ด้วยอาร์เรย์ voxel ที่ค่อนข้างคงที่สิ่งที่มีประสิทธิภาพมากขึ้น: การใช้ CPU เพื่อสร้าง VBO ล่วงหน้าเพื่อแสดงใบหน้าของ voxel (โดยไม่สนใจรูปแบบการแสดงผลขั้นสูงเช่นการเดินขบวนลูกบาศก์ในตอนนี้) หรือการใช้เรขาคณิต shader บน GPU เพื่อสร้าง เผชิญกับการบิน?

ฉันไม่ได้กังวลเกี่ยวกับการอัปเดตการเปลี่ยนแปลง voxels แต่แน่นอนว่าเป็นประโยชน์ของรุ่น GPU เนื่องจากคุณไม่จำเป็นต้องสร้าง VBO ใหม่ นอกจากนี้วิธีการ GS ยังให้ความรู้สึกทันสมัยยิ่งขึ้น :)

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

คำตอบ:


9

ฉันกำลังคิดถึงฉากประเภท minecraft โดย voxel คุณหมายถึงโลกของบล็อกที่แสดงผลโดยใช้รูปหลายเหลี่ยม:

หากคุณใช้รูปทรงเรขาคณิตมันจะยากที่จะหลีกเลี่ยงการมีสามใบหน้า (หรืออะไรก็ตาม) ต่อ voxel

หากคุณมีบล็อกที่อยู่ติดกันจำนวนมากที่มีพื้นผิวเดียวกันคุณสามารถใช้การเรียงตัวของพื้นผิวเพื่อให้มีสามเหลี่ยมน้อยลงในแถบ (เสื่อม) ของคุณด้วยวิธี VBO ฉันหมายความว่าถ้ามีพื้นที่หญ้า voxels ขนาดใหญ่แบน 6x6 ที่ดีคุณสามารถวาดยอดทั้งรูปในรูปสามเหลี่ยม 2 อันแทนที่จะเป็น 64

ด้วยวิธีการของ GS คุณไม่สามารถทำการคัดสรรใบหน้าที่เกิดจาก voxels ที่อยู่ติดกันซึ่งตรงไปตรงมามากด้วยวิธี VBO

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

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

ด้วยการใช้ pixmaps แบบเรียงต่อกันเป็นแนวตั้งในแผนที่ด้วยGL_REPEATบนแกนนอนและมี pixmaps ที่หมุนได้ 90 องศาในแผนที่เดียวกันฉันพบว่าฉันสามารถวาดบล็อกที่แตกต่างกันจำนวนมากโดยใช้ VBO เดียวกันในการโทรเดียวกัน ในตัวอย่างพื้นที่หญ้า 6x6 ฉันจะแบ่งมันออกเป็น 12 สามเหลี่ยมเพราะฉันทำซ้ำในมิติเดียวในแผนที่ของฉัน

ฉันได้รับสิ่งนี้เป็นส่วนใหญ่ในการทำงานกับชิปกราฟิกและโทรศัพท์มือถือในระดับต่ำสุดซึ่ง GS เป็นเพียงสิ่งที่ฉันสามารถฝันได้เกี่ยวกับการเล่นหนึ่งวัน


3
คุณต้องวาดได้ไม่เกิน 3 ใบหน้าต่อ voxel แต่คุณอาจต้องวาดใบหน้าที่แตกต่างกันสำหรับแต่ละ voxel ขึ้นอยู่กับมุมมองดังนั้นการปรับให้เหมาะสมนั้นไม่ใช่เรื่องง่ายใช่มั้ย VBO ที่สร้างไว้ล่วงหน้าจะมี voxel มากกว่าหนึ่ง หากมุมมองของคุณอยู่ในระหว่าง voxels คุณจะเห็นด้านตะวันออกของด้านหนึ่งและด้านตะวันตกของอีกด้านหนึ่ง วิธีเดียวที่จะช่วยได้คือคุณสามารถกำจัดใบหน้าที่หันไปทางด้านหลังเล็กน้อย แต่ในกรณีที่เลวร้ายที่สุดคือคุณยังคงแสดง 5 ใน 6 กลุ่มในกลุ่มของ voxels หากมุมมองของคุณอยู่นอกขอบเขตตามแนวแกนของ VBO คุณจะต้องแสดงผล 3 ด้านเท่านั้น
Bjorn Wesen

จุดบน Bjorn มันเป็นไปได้ ( แต่ผมกำลังสร้าง VBOs บล็อกตามความจำเป็นและหารือสิ่งที่ผมได้สร้างขึ้นเมื่อกล้องเคลื่อนมากกว่าที่มีทั่วโลกใน VBOs ตลอดเวลาดังนั้นฉันมีเวลาที่ธรรมชาติจะทำให้ตัวเลือกเหล่านี้)
Will

10

สิ่งที่เกี่ยวกับตัวเลือกที่สามโดยใช้อาร์เรย์ instanced? โดยทั่วไปคุณจะวาดกล่องจำนวนมาก (ทำจาก 8-vertex cube แบบง่ายๆ) ด้วยการเรียกแบบดึงครั้งเดียวจัดหาตำแหน่ง (และข้อมูลอื่น ๆ ) เป็นแอตทริบิวต์ต่อตัวอย่างจาก voxel-data VBO (ใช้glVertexAttribDivisorใน OpenGL ฉันแน่ใจ DX ก็มีเช่นกัน) นี่อาจจะเร็วกว่าวิธีเรขาคณิต shader แม้ว่ารหัสแอปพลิเคชัน (ไม่ใช่ shader) ควรจะค่อนข้างคล้ายกันเพราะฉันจำได้ว่าเฉดสีเรขาคณิตมีชื่อเสียงว่าเป็นช้าแม้ว่าฉันจะไม่มีประสบการณ์กับพวกเขา (หรืออินสแตนซ์) ขณะที่ฉันยังนั่ง บนฮาร์ดแวร์ 2.1

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


ใช่นี่เป็นทางออกที่ดีที่สุดสำหรับปัญหานี้ ทำไมไม่เกิดขึ้นกับฉัน :)
Notabene

หลังจากการทดลองบางอย่างฉันต้องบอกคุณว่ารูปทรงเรขาคณิตที่ได้รับการตีเต้นจะเกิดขึ้นโดยขอบที่กว้าง ฉันยังไม่ได้ลองรูปทรงเรขาคณิต
Jari Komppa

@JariKomppa คุณสามารถอธิบายเพิ่มเติมเกี่ยวกับสิ่งที่คุณหมายถึงโดยเรขาคณิตอบ?
Steven Lu

อินสแตนซ์ที่แปลล่วงหน้าและคัดลอกไปยังตาข่ายเดียว เหมือนมีตาข่ายหนึ่งอันที่แสดงถึงหนึ่งร้อยลูกบาศก์หรืออะไรก็ตาม
Jari Komppa

@JariKomppa ฉันเห็นผลลัพธ์เดียวกันซึ่งการสร้างตาข่ายนั้นเร็วกว่ามาก อย่างไรก็ตามใน gtx 680 ตัวเลือก instancing ดูเหมือนว่าจะทำงานได้เร็วขึ้นแปลกมาก
Levi H

1

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

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

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


2
มันอาจจะเป็นความคิดที่ดีที่จะตรวจสอบ voxels ที่อยู่ติดกันในรูปทรงเรขาคณิตและ / หรือจุดยอด shader และละทิ้งจุดยอดหรือข้ามใบหน้าหากพวกเขาถูกบัง มิฉะนั้นโซลูชัน GS จะเพิ่มแบนด์วิดท์ที่ใช้แทน
Tamschi

Bandwith จะไม่เป็นปัญหาใหญ่ (จากประสบการณ์ของฉัน) แต่แน่นอนว่ามันเป็นเรื่องจริง และคุณไม่สามารถค้นหาใน primitives อื่น ๆ ใน GS (คือฉันรู้ว่า :))
Notabene

@ แทมชิ: ใช่ปัญหานี้เกิดขึ้นกับฉันหลังจากที่เขียนคำถามนี้ .. สำหรับซีพียูเวอร์ชั่น, voxels ในช่วงกลางของของแข็งจะถูกระงับ แต่อาจเป็นไปไม่ได้ใน GPU โดยไม่ต้องผ่านก่อนกับสิ่งที่จะเป็นจำนวน differencing ..
Bjorn Wesen

1
คุณสามารถผูกบัฟเฟอร์จุดสุดยอดกับชุด isamplerBuffer หรือ usamplerBuffer ใน shader จากนั้นทำการค้นหาด้วย texture (name_of_uniform, index) อีกทางเลือกหนึ่งคือการผูกบัฟเฟอร์กับอาร์เรย์ที่เหมือนกันซึ่งจะช่วยให้คุณมีอิสระมากขึ้นในรูปแบบจุดยอดที่คุณต้องการใช้
Tamschi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.