SpriteBatch ของ XNA ทำงานอย่างไร


38

เพื่อให้แม่นยำยิ่งขึ้นถ้าฉันต้องการสร้างฟังก์ชันการทำงานนี้ใหม่อีกครั้งตั้งแต่เริ่มต้นใน API อื่น (เช่นใน OpenGL) สิ่งที่จำเป็นต้องทำ

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

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

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


มีลักษณะที่วิธีการที่จะดำเนินการใน MonoGame ผ่าน OpenGL A: github.com/mono/MonoGame/blob/master/MonoGame.Framework/...
Den

คุณลองใช้ DotPeek หรือ Reflector บน Microsoft.Xna.Graphics (ฉันไม่แนะนำให้ทำอะไรผิดกฎหมาย :)
ชัด

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

ใช่นั่นคือเหตุผลที่ฉันใช้ความคิดเห็น ฉันคิดว่า Andrew Russell อาจเป็นคนดีที่จะตอบคำถามนี้ เขาเป็นคนที่ใช้งานอยู่ในชุมชนแห่งนี้และเป็นคนที่ทำงาน Exen ซึ่งเป็นทางเลือกในการ MonoGame: andrewrussell.net/exen
ชัด

ใช่นี่เป็นคำถามที่ Andrew Russel (หรือ Shawn Hargreaves กลับมาที่ฟอรัม XNA) โดยปกติแล้วจะสามารถให้ข้อมูลเชิงลึกได้มากมาย
David Gouveia

คำตอบ:


42

ฉันได้จำลองพฤติกรรมของ SpriteBatch ในโหมดรอการตัดบัญชีสำหรับเครื่องมือข้ามแพลตฟอร์มที่ฉันกำลังทำงานอยู่ดังนั้นนี่คือขั้นตอนที่ฉันได้ทำวิศวกรรมย้อนกลับ:

  1. SpriteBatch สร้าง:สร้างDynamicIndexBuffer, DynamicVertexBufferและอาเรย์ของVertexPositionColorTextureขนาดคงที่ (ในกรณีนี้ขนาดสูงสุดชุด - 2,048 สำหรับสไปรท์และ 8192 สำหรับจุด)

    • บัฟเฟอร์ดัชนีเต็มไปด้วยดัชนีจุดสูงสุดของคณะสี่คนที่จะถูกดึง (0-1-2, 0-2-3, 4-5-6, 4-6-7 และอื่น ๆ )
    • อาร์เรย์ภายในของSpriteInfostructs ถูกสร้างขึ้นเช่นกัน สิ่งนี้จะจัดเก็บการตั้งค่าสไปรท์ชั่วคราวที่จะใช้เมื่อแบทช์
  2. SpriteBatch.Begin: จัดเก็บค่าของBlendState, SamplerStateฯลฯ ที่ระบุไว้ภายในและตรวจสอบว่ามันถูกเรียกสองครั้งโดยไม่ต้องSpriteBatch.Endอยู่ในระหว่าง

  3. SpriteBatch.Draw:จะใช้เวลาทั้งหมดข้อมูลเทพดา (เนื้อ, ตำแหน่ง, สี) SpriteInfoและสำเนาไปยัง หากถึงขนาดแบทช์สูงสุดชุดทั้งหมดจะถูกดึงเพื่อให้มีที่ว่างสำหรับสไปรต์ใหม่

    • SpriteBatch.DrawStringเพียงแค่ออกDrawสำหรับแต่ละตัวละครของสตริงโดยคำนึงถึงการจัดช่องไฟและระยะห่าง
  4. SpriteBatch.End:ทำการดำเนินการต่อไปนี้:

    • Beginชุดทำให้รัฐที่ระบุไว้ใน
    • สร้างเมทริกซ์การฉายภาพ orthographic
    • ใช้SpriteBatchshader
    • ผูกDynamicVertexBufferและDynamicIndexBuffer.
    • ดำเนินการแบตช์ต่อไปนี้:

      startingOffset = 0;
      currentTexture, oldTexture = null;
      
      // Iterate through all sprites
      foreach SpriteInfo in SpriteBuffer
      {
          // Store sprite index and texture
          spriteIndex = SpriteBuffer.IndexOf(SpriteInfo);
          currentTexture = SpriteInfo.Texture;
      
          // Issue draw call if batch count > 0 and there is a texture change
          if (currentTexture != oldTexture)
          {
              if (spriteIndex > startingOffset)
              {
                  RenderBatch(currentTexture, SpriteBuffer, startingOffset,
                              spriteIndex - startingOffset);
              }
              startingOffset = spriteIndex;
              oldTexture = currentTexture;
          }
      }
      
      // Draw remaining batch and clear the sprite data
      RenderBatch(currentTexture, SpriteBuffer, startingOffset,
                  SpriteBuffer.Count - startingOffset);
      SpriteBuffer.Clear();
      
  5. SpriteBatch.RenderBatch:ดำเนินการการดำเนินการต่อไปนี้สำหรับแต่ละรายการSpriteInfoในชุดงาน:

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

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

ดูเหมือนว่าฉันไม่สามารถหาได้ในเอกสารประกอบ - ขีด จำกัด ของการโทร Draw ที่คุณสามารถทำได้ก่อนที่บัฟเฟอร์จะเต็ม และการเรียก DrawText เติมบัฟเฟอร์นั้นด้วยจำนวนอักขระทั้งหมดในสตริงหรือไม่
David Gouveia

ที่น่าประทับใจ! เครื่องมือของคุณจะเปรียบเทียบกับ ExEn และ MonoGame อย่างไร มันจะต้องใช้ MonoTouch และ MonoAndroid ด้วยหรือไม่ ขอบคุณ
Den

@DavidGouveia: 2048 sprites เป็นขนาดแบทช์สูงสุด - แก้ไขคำตอบและเพิ่มเพื่อความสะดวก ใช่การจัดเรียงตามพื้นผิวและการให้ z-buffer ดูแลการสั่งซื้อสไปรต์จะใช้การเรียกการวาดขั้นต่ำ หากคุณต้องการลองใช้SpriteSortMode.Textureเพื่อวาดตามลำดับที่คุณต้องการและปล่อยให้SpriteBatchทำการเรียงลำดับ
r2d2rigo

1
@Den: ExEn และ MonoGame เป็น API ระดับล่างที่อนุญาตให้ใช้รหัส XNA ในแพลตฟอร์มที่ไม่ใช่ Windows โครงการที่ฉันกำลังทำอยู่เป็นเครื่องมือที่ใช้ส่วนประกอบที่เขียนใน C # แต่เราต้องการเลเยอร์ที่บางมากเพื่อให้สามารถเข้าถึง API ของระบบ (นั่นคือสิ่งที่ฉันกำลังทำงานอยู่) เราเพิ่งเลือกใช้งานอีกครั้งSpriteBatchเพื่อความสะดวก และใช่มันต้องใช้ MonoTouch / MonoDroid เนื่องจากเป็น C # ทั้งหมด!
r2d2rigo

13

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


+1 สำหรับ "รหัสที่ฉันจะไม่ใช้ แต่น่าสนใจที่จะอ่านมากกว่า"
Kyle Baran

รุ่นล่าสุดของ XNA SpriteBatch เป็นพื้นเมือง C ++ สามารถพบได้บนGitHub ชั่วโมง / CPP เป็นโบนัสรุ่น DirectX12 ยังมี h / cpp
Chuck Walbourn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.