ฉันควรจะใช้สไปรต์ฮีตเพราะรูปภาพจำนวนมากมายของฉันหรือไม่?


13

ฉันกำลังพัฒนาเกม 2D และฉันมีสไปรต์มากมาย ฉันใช้ภาพเคลื่อนไหวและโมเดล 3 มิติเพื่อแสดงเป็น 2D เพื่อให้พวกเขาเห็นว่า "Fallout" หรือ "Diablo" นอกจากนี้ยังง่ายกว่าการวาดด้วยมือฮ่า ๆ

ฉันต้องลดอัตราเฟรมลงเหลือ 15 เฟรมต่อวินาทีซึ่งต่ำที่สุดที่ฉันสามารถลดได้โดยไม่ทำให้พวกเขาดูขาด ๆ หาย ๆ อย่างไรก็ตามมันเป็นเรื่องน่าเศร้าเนื่องจากมี 24 เฟรมที่ดูราบรื่น

มีสองเหตุผลที่ฉันทำสิ่งนี้:

1) ลดพื้นที่ HDD ยิ่งภาพน้อยลงเท่าไหร่เกมของฉันก็ยิ่งเล็กลงเท่านั้น

2) ลดปริมาณการใช้ RAM ยิ่งฉันโหลดภาพน้อยลงเท่าไหร่ฉันก็ยิ่งมีแนวโน้มที่จะหลีกเลี่ยงปัญหาที่ทำให้เกิดข้อ จำกัด RAM ของฉันมากขึ้นเท่านั้น

อย่างไรก็ตามหากมีวิธีการบีบอัดภาพในพื้นที่ HDD และ RAM ฉันจะทำเช่นนั้น ฉันได้ทำการทดสอบมาก่อนและส่วนใหญ่ไม่ได้รับการเปลี่ยนแปลงคุณภาพใด ๆ เมื่อให้จาก RGBA8888 เป็น RGBA5555 และมีการเข้าชมเพียงเล็กน้อยเมื่อแปลงเป็น RGBA4444 ในโปรแกรม TexturePacker ของฉัน ฉันไม่ได้ทำเช่นนี้ในขณะนี้เนื่องจาก SFML ดูเหมือนว่าจะใช้หน่วยความจำในปริมาณเท่ากันไม่ว่าจะเป็นรูปภาพ. PNG ประเภทใด ฉันค้นหาการค้นคว้าวิธีโหลดมันแตกต่างกัน แต่ไม่พบสิ่งใดในหัวข้อ

ฉันได้อ่านมากเกี่ยวกับวิธีจัดการกับวิดีโอเกม 2 มิติ ฉันทามติเป็นอย่างยิ่ง: จัด Sprite ของคุณลงใน Texture Bigger เพื่อประสิทธิภาพที่ยอดเยี่ยม! ดังนั้นฉันจึงบรรจุสไปรต์ตัวจิ๋วของฉันไปไว้ในสไปรต์ชีตที่ใหญ่กว่ามากโดยใช้ TexturePacker

อย่างไรก็ตามฉันวางแผนที่จะมีแอนิเมชั่น 10-15 ตัวต่อตัวละคร 5 ทิศทางในการย้ายและ 15-40 เฟรมต่อภาพเคลื่อนไหว (อาจเป็นค่าเฉลี่ย 24) ด้วยภาพเคลื่อนไหว 15 ภาพ, 5 ทิศทางและค่าเฉลี่ย 24 เฟรมต่อภาพเคลื่อนไหว; นั่นคือ 1800 แต่ละเฟรมต่อตัวละคร หากบรรจุในแผ่นสไปรต์นั่นเป็นเพียง 75 ภาพแทน (หนึ่งแผ่นสไปรต์ต่อภาพเคลื่อนไหวต่อทิศทาง 15 * 5)

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

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

ถ้าฉันจะโหลดพื้นผิวล่วงหน้ามันสมเหตุสมผลสำหรับแผ่นผีสาง ฉันแค่คิดว่ามันเป็นความคิดที่ดีที่จะโหลดภาพขนาดเล็ก 1800 ภาพสำหรับตัวละครแต่ละตัว

อย่างไรก็ตามฉันนึกภาพการสตรีมเข้าและออกจากหน่วยความจำทีละครั้งจะเร็วมากดังนั้นฉันจะต้องมีเพียงภาพเดียวในหน่วยความจำในคราวเดียว นี่ไม่ได้หมายความว่าในเวลาใดก็ตามฉันจะให้ตัวละครแต่ละตัวกินเนื้อที่เพียงไม่กี่ KB แทนที่จะเป็น 45 + MB?

ฉันคิดว่าสิ่งนี้จะฆ่าการแสดงของฉันเนื่องจากการสตรีมจะต้องรวดเร็วอย่างไม่น่าเชื่อ (15 ภาพที่จะเข้าและออกจากหน่วยความจำและการเรนเดอร์ต่อวินาที) และแม้ว่าภาพจะมีขนาดเล็กมาก ลงในหน่วยความจำแทน แต่ฉันจะต้องเขียนโค้ดระบบเรนเดอร์ที่มีภาพเหมือนภาพเดียวสำหรับตัวละครที่ใหญ่กว่าของฉัน

ฉันทดลองมาแล้ว แต่มันไม่ใช่กระบวนการง่ายๆ โดยเฉพาะอย่างยิ่งความจริงที่ฉันกำลังทำงานในส่วนอื่น ๆ ของเกมเอ็นจิ้นที่ไม่ได้จัดการกับกราฟิกในขณะนี้


1. คุณไม่ได้ระบุข้อ จำกัด RAM หรือ HDD ของคุณ ต้องมีอักขระกี่ตัวในการเข้าถึงที่รวดเร็ว 2. มีคำถามหลายข้อตามข้อความคุณอาจจะเน้นพวกมันด้วยตัวหนาหรือแยกคำถามเป็นส่วน ๆ ?
Kromster

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

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

ต้องมีอักขระ UNIQUE กี่ตัวบนหน้าจอ
Kromster

ไม่เกิน 20 สิ่งที่อยู่เหนือที่เป็นไปไม่ได้นอกจากว่าพวกเขาโกง โดยทั่วไปแล้ว 5-10
Carter81

คำตอบ:


16

เรามีกรณีที่คล้ายคลึงกับ RTS Remake ของเรา ทุกยูนิตและบ้านเป็นสไปรท์ เรามีสไปรต์ 18,000 สำหรับหน่วยและบ้านและภูมิประเทศรวมถึงอีก 6,000 ~ สำหรับสีทีม (ใช้เป็นมาสก์) ยืดเยื้อเรามีตัวอักษรประมาณ 30,000 ตัวอักษรใช้

ดังนั้นเหตุผลหลักที่อยู่เบื้องหลังแผนที่คือ:

  • RAM ที่สูญเปล่าน้อยกว่า (ในวันที่เก่ากว่าเมื่อคุณอัปโหลด NPOT ไปยัง GPU มันยืด / เพิ่มเป็น POT ฉันอ่านมันยังคงเหมือนเดิมกับ iOS และเฟรมเวิร์กคุณควรตรวจสอบช่วงของฮาร์ดแวร์ที่คุณกำหนดเป้าหมาย)
  • สวิทช์พื้นผิวน้อยลง
  • โหลดเร็วขึ้นของทุกอย่างในกลุ่มที่ใหญ่น้อยลง

สิ่งที่ไม่ได้ผลสำหรับเรา:

  • พื้นผิว paletted ฟีเจอร์นี้มีอยู่ใน OpenGL 1.x 2.x เท่านั้นและผู้ผลิต GPU ส่วนใหญ่จะถูกทิ้งไว้ อย่างไรก็ตามหากคุณมุ่งหวังที่ OpenGL + Shaders คุณสามารถทำได้ในรหัส shaders ด้วยตัวคุณเองก็ดี!
  • พื้นผิว NPOT เรามีปัญหาเกี่ยวกับเส้นขอบที่ไม่ถูกต้องและสไปรต์เบลอซึ่งไม่สามารถยอมรับได้ในศิลปะพิกเซล การใช้ RAM ก็สูงขึ้นมากเช่นกัน

ตอนนี้เรามีทุกอย่างที่บรรจุในแผนที่ 1024x1024 หลายสิบ (GPU สมัยใหม่รองรับขนาดที่ใหญ่กว่า) และใช้งานได้ดีกินหน่วยความจำเพียง ~ 300mb ซึ่งค่อนข้างดีสำหรับเกมพีซี การเพิ่มประสิทธิภาพบางอย่างที่เรามี:

  • เพิ่มตัวเลือกผู้ใช้เพื่อใช้ RGB5_A1 แทน RGBA8 (เงากระดานหมากรุก)
  • หลีกเลี่ยง 8bit Alpha เมื่อเป็นไปได้และใช้รูปแบบ RGB5_A1
  • แพ็คสไปรต์แน่นเป็น atlases (ดูอัลกอริธึม Bin Packing)
  • จัดเก็บและโหลดทุกอย่างในหนึ่งชิ้นจาก HDD (ไฟล์ทรัพยากรควรสร้างแบบออฟไลน์)
  • คุณอาจลองใช้รูปแบบการบีบอัดฮาร์ดแวร์ (DXT, S3TC เป็นต้น)

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


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

5

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

เวลาโหลด:

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

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

ประสิทธิภาพการแสดงผล:

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

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

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

    การปรับระดับที่เหมาะสมนั้นไม่สำคัญ แต่โดยทั่วไปคุณสามารถจัดกลุ่มสไปรต์จากชั้นเดียวกันได้อย่างปลอดภัย ตัวอย่างเช่นการมีรายการ GUI ทั้งหมดในแผ่นงานหนึ่งแผ่นเป็นแนวคิดที่มีแนวโน้มมากในขณะที่การจัดกลุ่มมอนสเตอร์อาจไม่สามารถเรียงลำดับตัวอักษรได้

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

  3. จำนวนสามเหลี่ยม:อันที่จริงแล้วยิ่งคุณวาดรูปสามเหลี่ยมได้มากเท่าไหร่ก็จะยิ่งใช้เวลาวาดนานขึ้นเท่านั้น อย่างไรก็ตามในคอมพิวเตอร์ที่ทันสมัยและสำหรับเกม 2D ส่วนใหญ่คุณจะอยู่ห่างไกลจากสิ่งนี้ คุณสามารถวาดจำนวนสไปรต์ต่อเฟรมอย่างปลอดภัยและยังคงได้รับเฟรมเมเรียมที่ดีอย่างบ้าคลั่ง คุณอาจจะผูกพันกับ CPU มากขึ้นถ้าคุณวาดสไปรต์จำนวนมากก่อนที่คุณจะพบปัญหากับ GPU ของคุณ

  4. การตั้งค่า API:หากคุณทำทุกอย่างถูกต้องและคุณยังมีอัตราเฟรมต่ำแปลกให้ตรวจสอบการตั้งค่าที่คุณวาดสไปรต์ ฉันไม่รู้จัก SFML แต่อย่างเช่นใน Direct3D 9 การสร้างบัฟเฟอร์จุดสุดยอดด้วยD3DUSAGE_DYNAMICหรือในD3DPOOL_MANAGEDสามารถเพิ่มการเรนเดอร์ของคุณได้สิบเท่า แน่นอนว่าการใช้ vSync จะเพิ่มอัตราเฟรมของคุณในอัตรารีเฟรชของจอภาพ นอกจากนี้การใช้ FVF แบบไม่จัดชิดอาจลดประสิทธิภาพใน GPU บางตัว สิ่งนี้ก็เช่นกันสำหรับ Direct3D 9

    ในกรณีของคุณให้ตรวจสอบเอกสารสำหรับ API ที่คุณใช้

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


ถ้าฉันไม่สนใจเวลาในการโหลดฉันต้องสมมติว่าถ้าฉันไม่มี RAM หรือ VRAM ฉันควรโหลดทุกอย่างไว้ในหน่วยความจำก่อนหรือไม่?
Carter81

ฉันกังวลกับทุกอย่างเพียงเพราะฉันกลัวว่าจะใช้ RAM / VRAM ต่ำ ฉันไม่รู้ว่าทำไม แต่มันทำให้ฉันกลัวว่าผู้ใช้ที่เล่นเกมของฉันจะล้มเหลวเมื่อใดก็ตามที่พวกเขาพยายามโหลดลงในพื้นที่ที่มีสไปรต์ที่ไม่ซ้ำกันมากเกินไปหรือจะพังเมื่อใดก็ตามที่ตัวละครมากเกินไป ถ้าฉันไม่เข้าใจผิดและเทพดาแต่ละตัวใช้ 96KB ดังนั้นถ้าตัวละครแต่ละตัวมีภาพเคลื่อนไหว 15 ภาพ, 5 ทิศทางและ 24 เฟรมต่อภาพเคลื่อนไหวโดยเฉลี่ย - แต่ละตัวละครแต่ละตัวเต็มไปด้วย 173MB อาจมีอักขระ 10 ตัวหรือมากกว่าบนหน้าจอพร้อมกัน
Carter81

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

1
@ Carter81: คุณต้องเลือกการกำหนดค่าฮาร์ดแวร์เป้าหมายเช่น "i5, 1gb RAM, NVidia GT260, 400mb hdd" และทำงานจากนั้น จะมีพีซีที่อ่อนแอกว่าและมี RAM น้อยกว่าเสมอ
Kromster

เห็นได้ชัดว่าพวกเขาไม่ต้องการภาพเคลื่อนไหวทั้ง 15 ภาพในเวลาใดก็ตาม อย่างไรก็ตามจะเกิดอะไรขึ้นถ้าตัวละครที่ไม่ซ้ำใครทั้ง 10 ตัวเข้าสู่ "โหมดการต่อสู้" ในเวลาเดียวกันและต้องใช้ภาพเคลื่อนไหว 5 ชุด (เดิน, วิ่ง, ไม่ได้ใช้งาน, ไม่ต่อสู้ ฯลฯ ) เพื่อสลับกับอีก 5 (การต่อสู้เดิน การต่อสู้ไม่ได้ใช้งานการต่อสู้ ฯลฯ )? ฉันกลัวการเปลี่ยนพื้นผิวเพราะเมื่อฉันลองทำกับ SFML มันจะสร้างการหยุดหรือหยุดชั่วคราวของลูกค้าเมื่อสังเกตเห็นการสลับ atlases พื้นผิว ฉันไม่รู้ว่าคอขวดของฉันจะเป็นอย่างไรกับกลยุทธ์ต่าง ๆ เพื่อจัดการกับสไปรต์มากมาย
Carter81
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.