ฉันจะปรับปรุงความเร็วการเรนเดอร์ของเกมประเภท Voxel / Minecraft ได้อย่างไร?


35

ฉันกำลังเขียนโคลนของ Minecraft เอง (เขียนด้วยภาษาจาวา) มันใช้งานได้ดีในขณะนี้ ด้วยระยะการดู 40 เมตรฉันสามารถกด 60 FPS บน MacBook Pro 8,1 ได้อย่างง่ายดาย (Intel i5 + Intel HD Graphics 3000) แต่ถ้าฉันวางระยะทางในการมองที่ 70 เมตรฉันจะไปถึง 15-25 FPS ใน Minecraft ตัวจริงฉันสามารถใส่ความไม่ลงรอยกันในการมองไกล (= 256m) ได้โดยไม่มีปัญหา ดังนั้นคำถามของฉันคือฉันควรทำอย่างไรเพื่อทำให้เกมของฉันดีขึ้น?

การเพิ่มประสิทธิภาพที่ฉันใช้:

  • เก็บเฉพาะชิ้นส่วนในหน่วยความจำเท่านั้น (ขึ้นอยู่กับระยะการมองของผู้เล่น)
  • Frustum culling (ครั้งแรกบนชิ้นแล้วบนบล็อก)
  • วาดเฉพาะใบหน้าที่มองเห็นได้จริงๆของบล็อกเท่านั้น
  • ใช้รายการต่ออันที่มีบล็อกที่มองเห็นได้ ส่วนที่มองเห็นได้จะเพิ่มเข้าไปในรายการนี้ หากพวกเขากลายเป็นล่องหนพวกเขาจะถูกลบออกจากรายการนี้โดยอัตโนมัติ บล็อกกลายเป็น (ใน) มองเห็นได้โดยการสร้างหรือทำลายบล็อกเพื่อนบ้าน
  • การใช้รายการต่ออันประกอบด้วยบล็อกการปรับปรุง กลไกเดียวกับรายการบล็อกที่มองเห็นได้
  • ใช้newคำสั่งแทบไม่มีในลูปเกม (เกมของฉันทำงานประมาณ 20 วินาทีจนกระทั่งตัวรวบรวมข้อมูลขยะถูกเรียกใช้)
  • ฉันใช้รายการโทร OpenGL ในขณะนี้ ( glNewList(), glEndList(), glCallList()) สำหรับแต่ละด้านของชนิดของบล็อก

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

มีเทคนิคอื่น ๆ เพื่อปรับปรุงประสิทธิภาพหรือไม่?

การทำโปรไฟล์ VisualVM แสดงให้ฉันเห็น (การทำโปรไฟล์สำหรับ 33 เฟรมเท่านั้นด้วยระยะการดู 70 เมตร):

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

การทำโปรไฟล์ 40 เมตร (246 เฟรม):

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

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

แก้ไข:หลังจากลบบางsynchronisedบล็อกและการปรับปรุงเล็กน้อยอื่น ๆ ประสิทธิภาพนั้นดีขึ้นมากแล้ว นี่คือผลลัพธ์การรวบรวมสถานะใหม่ของฉันที่มี 70 เมตร:

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

ฉันคิดว่ามันค่อนข้างชัดเจนว่าselectVisibleBlocksเป็นปัญหาที่นี่

ขอบคุณล่วงหน้า!
Martijn

อัปเดต : หลังจากการปรับปรุงพิเศษบางอย่าง (เช่นการใช้ลูปแทนแต่ละตัวการกำหนดบัฟเฟอร์ตัวแปรภายนอกลูป ฯลฯ ... ) ตอนนี้ฉันสามารถเรียกใช้ระยะการดู 60 ได้ค่อนข้างดี

ฉันคิดว่าฉันจะใช้ VBO โดยเร็วที่สุด

PS: ซอร์สโค้ดทั้งหมดมีอยู่ใน GitHub:
https://github.com/mcourteaux/CraftMania


2
คุณสามารถให้โปรไฟล์กับเราที่ระยะ 40 ม. เพื่อให้เราเห็นได้ว่าอาจมีการขยายขนาดเร็วกว่าอีกบ้างไหม
James

อาจระบุไว้ด้วย แต่ถ้าคุณพิจารณาก็แค่ถามถึงเทคนิคของการเร่งเกม 3 มิติให้เสียงที่น่าสนใจ แต่ชื่ออาจตกใจ ppl
Gustavo Maciel

@Gtoknu: คุณแนะนำอะไรเป็นชื่อ?
Martijn Courteaux

5
บางคนอาจบอกว่า Minecraft นั้นไม่ได้เร็วขนาดนั้นขึ้นอยู่กับว่าคุณถามใคร
thedaian

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

คำตอบ:


15

คุณพูดถึงการทำ frustum คัดสรรในแต่ละบล็อก - ลองโยนที่ ชิ้นเรนเดอร์ส่วนใหญ่ควรมองเห็นได้อย่างสมบูรณ์หรือมองไม่เห็น

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

นอกจากนี้คุณดูเหมือนจะใช้ชิ้นส่วนที่มีความสูงระดับโลก โปรดทราบว่า Minecraft ใช้ลูกบาศก์ขนาด 16 × 16 × 16 สำหรับรายการแสดงผลซึ่งแตกต่างจากโหลดและบันทึก หากคุณทำเช่นนั้นมีเหตุผลที่น้อยกว่าที่จะคัดชิ้นส่วนบุคคล

(หมายเหตุ: ฉันยังไม่ได้ตรวจสอบรหัสของ Minecraft ข้อมูลทั้งหมดนี้เป็นข่าวลือหรือข้อสรุปของฉันเองจากการสังเกตการแสดงผลของ Minecraft ขณะที่ฉันเล่น)


คำแนะนำทั่วไปเพิ่มเติม:

โปรดจำไว้ว่าการเรนเดอร์ของคุณดำเนินการกับโปรเซสเซอร์สองตัว: CPU และ GPU เมื่ออัตราเฟรมของคุณไม่เพียงพอหนึ่งในนั้นคือทรัพยากรที่ จำกัด - โปรแกรมของคุณเป็นCPU-boundหรือGPU-bound (สมมติว่ามันไม่ได้แลกเปลี่ยนหรือมีปัญหาเกี่ยวกับการตั้งเวลา)

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

ในทางกลับกันหาก GPU มีขีด จำกัด (น่าเศร้ามักจะไม่สะดวกในการตรวจสอบโหลด 0% -100%) คุณควรคิดถึงวิธีการส่งข้อมูลให้น้อยลงหรือต้องการเติมพิกเซลให้น้อยลง


2
การอ้างอิงที่ดีงานวิจัยของคุณที่กล่าวถึงในวิกิของคุณมีประโยชน์กับฉันมาก +1
Gustavo Maciel

@OP: แสดงเฉพาะใบหน้าที่มองเห็นได้ (ไม่ใช่บล็อก ) ก้อนขนาด 16x16x16 ซึ่งมีลักษณะทางพยาธิวิทยา แต่มีขนาดเล็กจะมีใบหน้าที่มองเห็นได้เกือบ 800 ใบหน้าในขณะที่บล็อกที่มีอยู่นั้นจะมีใบหน้าที่มองเห็นได้ 24,000 ใบหน้า เมื่อคุณทำเสร็จแล้วคำตอบของ Kevin ประกอบด้วยการปรับปรุงที่สำคัญที่สุดถัดไป
AndrewS

@KevinReid มีบางโปรแกรมที่ช่วยแก้ไขข้อบกพร่องด้านประสิทธิภาพ ตัวอย่างเช่น AMD GPU PerfStudio จะบอกคุณว่า CPU หรือ GPU ของมันเชื่อมโยงกับ GPU หรือไม่และส่วนประกอบอะไรที่ถูกผูกไว้ (texture vs fragment vs vertex ฯลฯ ) และฉันมั่นใจว่า Nvidia มีบางอย่างที่คล้ายกัน
akaltar

3

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

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

หากการนับ "เรียกใช้" นั้นถูกต้องในโปรไฟล์ของคุณคุณกำลังโทรหาหลายสิ่งหลายอย่างที่แย่มาก ๆ (10 ล้านสายไปที่ Vec3f.set ... อุ๊ย!)


ฉันใช้วิธีนี้กับสิ่งต่างๆมากมาย มันตั้งค่าสามค่าสำหรับเวกเตอร์ สิ่งนี้ดีกว่าการจัดสรรแต่ละครั้งที่มีวัตถุใหม่
Martijn Courteaux

2

คำอธิบายของฉัน (จากการทดลองของฉันเอง) ที่นี่ใช้ได้:

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

Minecraft และรหัสของคุณน่าจะใช้ฟังก์ชั่นคงที่ ความพยายามของฉันเองได้อยู่กับ GLSL แต่โดยทั่วไปแล้วฉันรู้สึกว่า:

(จากหน่วยความจำ) ฉันสร้าง frustum ที่มีขนาดครึ่งบล็อกใหญ่กว่า frustum ของหน้าจอ จากนั้นฉันทดสอบจุดศูนย์กลางของแต่ละก้อน ( minecraft มีบล็อก 16 * 16 * 128 )

ใบหน้าในแต่ละหน้ามีช่วง VBO แบบองค์ประกอบ (ใบหน้าจำนวนมากจากชิ้นส่วนแบ่งปัน VBO เดียวกันจนกว่าจะเป็น 'เต็ม'; คิดเช่นmallocนั้นกับพื้นผิวเดียวกันใน VBO เดียวกันที่เป็นไปได้) และดัชนีจุดสุดยอดสำหรับทางทิศเหนือ ใบหน้า, ใบหน้าใต้และอื่น ๆ อยู่ติดกันมากกว่าแบบผสม เมื่อฉันวาดฉันทำglDrawRangeElementsเพื่อใบหน้าเหนือโดยปกติฉายแล้วและปกติในเครื่องแบบ จากนั้นฉันก็หันไปทางทิศใต้และอื่น ๆ ดังนั้นบรรทัดฐานไม่ได้อยู่ใน VBO ใด ๆ สำหรับแต่ละก้อนฉันต้องปล่อยใบหน้าที่จะมองเห็นได้ - เฉพาะใบหน้าที่อยู่ตรงกลางของหน้าจอเท่านั้นที่จะต้องวาดด้านซ้ายและขวาเช่น ง่ายGL_CULL_FACEในระดับแอปพลิเคชัน

การเร่งความเร็วที่ใหญ่ที่สุดคือ iirc ถูกกำจัดใบหน้าด้านในเมื่อทำการเรียงหลาย ๆ อัน

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

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


ฉันชอบแนวคิดของการเพิ่มประสิทธิภาพ frustum ของคุณ แต่คุณไม่ได้รวมคำว่า "บล็อก" และ "ก้อน" ไว้ในคำอธิบายของคุณใช่ไหม
Martijn Courteaux

อาจจะใช่. กลุ่มของบล็อกคือบล็อกของบล็อกในภาษาอังกฤษ
Will

1

การเปรียบเทียบทั้งหมดของคุณBlockDistanceComparatorมาจากไหน ถ้ามันมาจากฟังก์ชั่นการจัดเรียงนั้นจะถูกแทนที่ด้วยการเรียงลำดับแบบ Radix (ซึ่ง asymptotically เร็วกว่าและไม่ใช่การเปรียบเทียบตาม)

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

struct DistanceIndexPair
{
    float m_distanceSquaredFromOrigin;
    int m_index;
};

แล้วใน pseudoCode

// for i = 0..numBlocks
//     distanceIndexPairs[i].m_distanceSquaredFromOrigin = ...;
///    distanceIndexPairs[i].m_index = i;
// sort distanceIndexPairs
// for i = 0..numBlocks
//    sortedBlock[i] = unsortedBlocks[ distanceIndexPairs.m_index ]

ขออภัยหากนั่นไม่ใช่โครงสร้าง Java ที่ถูกต้อง (ฉันไม่ได้แตะ Java ตั้งแต่ระดับปริญญาตรี) แต่หวังว่าคุณจะเข้าใจ


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

1

ใช่ใช้ VBOs และ CULL หันหน้าเข้าหา แต่นั่นก็ทำให้เกมทุกเกม สิ่งที่คุณต้องการจะทำคือการแสดงผลลูกบาศก์หากผู้เล่นมองเห็นได้และหากบล็อกสัมผัสในวิธีเฉพาะ (สมมติว่าก้อนที่คุณมองไม่เห็นเพราะมันอยู่ใต้ดิน) คุณเพิ่มจุดยอดของบล็อกและสร้าง มันเกือบจะเหมือน "บล็อกที่ใหญ่กว่า" หรือในกรณีของคุณ - อัน สิ่งนี้เรียกว่าการโลภแบบตาข่ายและเพิ่มประสิทธิภาพอย่างมาก ฉันกำลังพัฒนาเกม (ใช้ voxel) และใช้อัลกอริธึมแบบโลภ

แทนที่จะแสดงทุกอย่างเช่นนี้

ทำให้

มันแสดงผลแบบนี้:

render2

ข้อเสียของสิ่งนี้คือคุณต้องทำการคำนวณเพิ่มเติมต่อชิ้นในการสร้างโลกครั้งแรกหรือหากผู้เล่นลบ / เพิ่มบล็อก

เครื่องยนต์ voxel ประเภทใดต้องการสิ่งนี้เพื่อประสิทธิภาพที่ดี

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

public void greedyMesh(int p, BlockData[][][] blockData){
        boolean[][][][] mask = new boolean[blockData.length][blockData[0].length][blockData[0][0].length][6];

    for(int side=0; side<6; side++){
        for(int x=0; x<blockData.length; x++){
            for(int y=0; y<blockData[0].length; y++){
                for(int z=0; z<blockData[0][0].length; z++){
                    if(data[x][y][z] > Material.AIR && !mask[x][y][z][side] && blockData[x][y][z].faces[side]){
                        if(side == 0 || side == 1){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=y; i<blockData[0].length; i++){
                                if(i == y){
                                    for(int j=z; j<blockData[0][0].length; j++){
                                        if(!mask[x][i][j][side] && blockData[x][i][j].id == blockData[x][y][z].id && blockData[x][i][j].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[x][i][z+j][side] || blockData[x][i][z+j].id != blockData[x][y][z].id || !blockData[x][i][z+j].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x][y+i][z+j][side] = true;
                                }
                            }

                            if(side == 0)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+1, y, z), new VoxelVector3i(x+1, y+height, z+width), new VoxelVector3i(1, 0, 0), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z+width), new VoxelVector3i(x, y+height, z), new VoxelVector3i(-1, 0, 0), Material.getColor(data[x][y][z])));
                        }else if(side == 2 || side == 3){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=x; i<blockData.length; i++){
                                if(i == x){
                                    for(int j=z; j<blockData[0][0].length; j++){
                                        if(!mask[i][y][j][side] && blockData[i][y][j].id == blockData[x][y][z].id && blockData[i][y][j].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[i][y][z+j][side] || blockData[i][y][z+j].id != blockData[x][y][z].id || !blockData[i][y][z+j].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x+i][y][z+j][side] = true;
                                }
                            }

                            if(side == 2)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y+1, z+width), new VoxelVector3i(x+height, y+1, z), new VoxelVector3i(0, 1, 0), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+width), new VoxelVector3i(x, y, z), new VoxelVector3i(0, -1, 0), Material.getColor(data[x][y][z])));
                        }else if(side == 4 || side == 5){
                            int width = 0;
                            int height = 0;
                            loop:
                            for(int i=x; i<blockData.length; i++){
                                if(i == x){
                                    for(int j=y; j<blockData[0].length; j++){
                                        if(!mask[i][j][z][side] && blockData[i][j][z].id == blockData[x][y][z].id && blockData[i][j][z].faces[side]){
                                            width++;
                                        }else{
                                            break;
                                        }
                                    }
                                }else{
                                    for(int j=0; j<width; j++){
                                        if(mask[i][y+j][z][side] || blockData[i][y+j][z].id != blockData[x][y][z].id || !blockData[i][y+j][z].faces[side]){
                                            break loop;
                                        }
                                    }
                                }
                                height++;
                            }
                            for(int i=0; i<height; i++){
                                for(int j=0; j<width; j++){
                                    mask[x+i][y+j][z][side] = true;
                                }
                            }

                            if(side == 4)
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x+height, y, z+1), new VoxelVector3i(x, y+width, z+1), new VoxelVector3i(0, 0, 1), Material.getColor(data[x][y][z])));
                            else
                                meshes.get(p).add(new Mesh(new VoxelVector3i(x, y, z), new VoxelVector3i(x+height, y+width, z), new VoxelVector3i(0, 0, -1), Material.getColor(data[x][y][z])));
                        }
                    }
                }
            }
        }
    }
}

1
และมันคุ้มค่าหรือไม่ ดูเหมือนว่าระบบ LOD จะเหมาะสมกว่า
MichaelHouse

0

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

คุณสามารถลองหาสภาพแวดล้อม Java ที่แตกต่างกันหรือเพียงแค่ยุ่งกับการตั้งค่าที่คุณมี แต่วิธีที่เรียบง่ายและเรียบง่ายในการสร้างโค้ดของคุณไม่ใช่เร็ว แต่การจัดการที่ช้าน้อยลงอย่างน้อยภายใน Vec3f หยุดอย่างน้อย การเข้ารหัส OOO * ทำให้ทุกวิธีประกอบด้วยตัวเองอย่าเรียกวิธีอื่นใด ๆ เพียงเพื่อทำงานที่ไม่ได้ใช้งาน

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

* วางวัตถุมากเกินไป


ใช่คุณจะประหยัดหน่วยความจำ แต่เสียซีพียู! ดังนั้น OOO จึงไม่ค่อยดีในเกมเรียลไทม์
Gustavo Maciel

ทันทีที่คุณเริ่มการทำโปรไฟล์ (และไม่ใช่แค่การสุ่มตัวอย่าง) การอินไลน์ใด ๆ ที่ JVM ปกติจะหายไป มันเหมือนกับทฤษฎีควอนตัมไม่สามารถวัดอะไรได้โดยไม่ต้องกำจัดผลลัพธ์: p
Michael

@Gtoknu นั่นไม่เป็นความจริงในระดับสากลใน OOO บางระดับการเรียกใช้ฟังก์ชั่นเริ่มต้นที่จะใช้หน่วยความจำมากขึ้นกว่ารหัสแบบอินไลน์ ฉันจะบอกว่ามีส่วนที่ดีของรหัสในคำถามที่อยู่รอบจุดคุ้มทุนสำหรับหน่วยความจำ
aaaaaaaaaaaa

0

คุณสามารถลองแบ่งการดำเนินการทางคณิตศาสตร์ให้เหลือผู้ประกอบการระดับบิตได้ หากคุณมีความพยายามที่จะทำให้ผู้ประกอบการค่าที่เหมาะสม:128 / 16 128 << 4สิ่งนี้จะช่วยได้มากกับปัญหาของคุณ อย่าพยายามทำให้ทุกอย่างทำงานได้อย่างเต็มประสิทธิภาพ ทำการอัปเดตเกมของคุณในอัตรา 60 หรืออะไรสักอย่างและแม้แต่ทำลายมันลงเพื่อสิ่งอื่น ๆ แต่คุณต้องทำลายและวาง voxels มิฉะนั้นคุณจะต้องทำรายการสิ่งที่ต้องทำซึ่งจะทำให้ fps ของคุณต่ำลง คุณสามารถอัปเดตอัตราประมาณ 20 รายการสำหรับเอนทิตี และบางอย่างเช่น 10 สำหรับการอัปเดตและหรือรุ่นของโลก

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