การใช้ XNA ContentPipeline เพื่อส่งออกไฟล์ในเครื่องที่ไม่มี XNA GS แบบเต็ม


9

เกมของฉันใช้ Content Pipeline เพื่อโหลด spriteSheet ตอนรันไทม์ ศิลปินของเกมส่ง spritesheet ที่ดัดแปลงแล้วมาให้ฉันและฉันจะสร้างในเครื่องของฉันและส่งโครงการที่อัปเดตให้เขา ดังนั้นฉันกำลังมองหาวิธีสร้างไฟล์ xnb ในเครื่องของเขา (นี่คือเอาต์พุตของไพพ์ไลน์เนื้อหา) โดยที่เขาไม่ต้องติดตั้งสตูดิโอ XNA Game แบบเต็ม

1) ฉันไม่ต้องการให้ศิลปินของฉันติดตั้ง VS + Xna (ฉันรู้ว่ามีรุ่นฟรีของ VS แต่จะไม่ขยายขนาดเมื่อเราเพิ่มผู้คนในทีมมากขึ้น) 2) ฉันไม่สนใจที่จะใช้เครื่องมือแก้ไข / แก้ไขนี้ใน Xbox เพื่อให้โซลูชัน Windows ใช้งานได้เท่านั้น 3) ฉันรู้ตัวเลือก MSBuild แต่พวกเขาต้องการ XNA แบบเต็ม

ฉันค้นคว้าบล็อกของ Shawn และพบตัวเลือกในการใช้ Msbuild Sampleหรือตัวเลือกใหม่ใน XNA 4.0 ที่ดูมีแนวโน้มที่นี่แต่ดูเหมือนว่าจะมีข้อ จำกัด เหมือนกัน: จำเป็นต้องติดตั้ง XNA GS เต็มเนื่องจาก ContentPipeline ไม่ได้เป็นส่วนหนึ่งของ XNA redist

มีใครพบวิธีแก้ปัญหาสำหรับสิ่งนี้?

คำตอบ:


11

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

เนื่องจากคุณเลือกเส้นทางนี้ฉันต้องเตือนคุณว่าจริงๆแล้วมันไม่ง่ายอย่างที่ใช้เพียงTexture2D.FromStreamสองเหตุผล:

ปัญหา # 1 - ขาดการสนับสนุนอัลฟาก่อนคูณ

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

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

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

ปัญหา # 2 - รูปแบบที่ไม่สนับสนุน

Texture2D.FromStreamท่อเนื้อหาสนับสนุนรูปแบบมากกว่า โดยTexture2D.FromStreamเฉพาะรองรับ png, jpg และ gif เท่านั้น ในทางตรงกันข้ามไปป์ไลน์เนื้อหารองรับ bmp, dds, dib, hdr, jpg, pfm, png, ppm และ tga หากคุณพยายามโหลดรูปแบบที่อัปโหลดผ่านTexture2D.FromStreamคุณจะได้รับInvalidOperationExceptionข้อมูลเพิ่มเติมเล็กน้อย

ฉันต้องการการสนับสนุน bmp ในเครื่องยนต์ของฉันจริงๆดังนั้นสำหรับกรณีนั้นฉันพบวิธีแก้ปัญหาที่ดูเหมือนว่าจะใช้ได้ ฉันไม่รู้เกี่ยวกับรูปแบบอื่น ๆ จับด้วยวิธีการของฉันคือการที่คุณจะต้องเพิ่มการอ้างอิงถึงSystem.Drawingการชุมนุมในโครงการของคุณเพราะมันจะทำให้การใช้งานของพระเจ้าที่สนับสนุนรูปแบบมากกว่าImage.FromStreamTexture2D.FromStream

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

โซลูชัน - เวอร์ชั่นง่าย (ช้ากว่า)

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

public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
    Texture2D texture = Texture2D.FromStream(graphicsDevice, stream);
    Color[] data = new Color[texture.Width * texture.Height];
    texture.GetData(data);
    for (int i = 0; i != data.Length; ++i)
        data[i] = Color.FromNonPremultiplied(data[i].ToVector4());
    texture.SetData(data);
    return texture;
}

หากคุณสนใจเกี่ยวกับ BMPs แล้วสิ่งที่คุณต้องทำคือการโหลดภาพกับ GDI แรกแล้วแปลงเป็น PNG Texture2D.FromStreamภายในก่อนที่จะผ่านไปยัง นี่คือรหัสที่ทำ:

// Load image using GDI because Texture2D.FromStream doesn't support BMP
using (Image image = Image.FromStream(stream))
{
    // Now create a MemoryStream which will be passed to Texture2D after converting to PNG internally
    using (MemoryStream ms = new MemoryStream())
    {
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Seek(0, SeekOrigin.Begin);
        texture = Texture2D.FromStream(_graphicsDevice, ms);
    }
}

โซลูชัน - เวอร์ชั่นที่ซับซ้อน (เร็วกว่า)

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

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

http://pastie.org/3651642

เพียงเพิ่มคลาสนั้นในโครงการของคุณและใช้ง่ายเหมือน:

TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");

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


ว้าวนี่มันเยี่ยมมาก! มันจะช่วยฉันได้มาก :) ขอบคุณมากเดวิดฉันขอบคุณมาก
krolth

+1 จริง ๆ แล้วฉันใช้FromStreamกับสตรีมหน่วยความจำที่มีบิตแมป 32 บิต (บันทึกเป็น png) เช่นเดียวกับตัวอย่างอื่น ๆ ของคุณ แต่วิธีนี้ไม่ได้สร้างพื้นผิวที่มีลักษณะหลายแบบก่อนกำหนด การลวงตาแต่ละครั้งอย่างชัดเจนในแต่ละสีนั้นเป็นเคล็ดลับขอบคุณ
Groo

3

ฉันคิดว่าทีมส่วนใหญ่จะยอมรับการเปลี่ยนแปลง xnb (เช่นกันการเปลี่ยนแปลงทั้งหมดจริง ๆ แล้ว xnb รวมถึงเซิร์ฟเวอร์ svn ของพวกเขา (ที่สามารถตั้งค่าได้ฟรี) และอนุญาตให้ผู้อื่น (ศิลปิน ฯลฯ ) อัปเดตสำเนาการทำงานของตนเอง

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

เครื่องชั่งนี้ก็ดีเหมือนกัน


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

@krolth มันเป็นเรื่องใหญ่ที่จะให้ศิลปินของคุณได้รับ VS Express และ XNA เป็นส่วนหนึ่งของการตั้งค่าให้ทำงานในโครงการหรือไม่? ฉันคิดว่า ณ จุดนี้การแลกเปลี่ยนของการเขียนคู่มือและช่วยให้ผู้คนผ่านมันจะเกินดุลประสิทธิภาพการผลิตที่คุณสูญเสียในขณะนี้เนื่องจากศิลปินไม่สามารถมองเห็นการทำงานของพวกเขาในเครื่องยนต์ เพื่อเพิ่มความคล่องตัวของกระบวนการให้ไฟล์. BAT ที่พวกเขาสามารถดับเบิลคลิกเพื่อคอมไพล์ทุกอย่างโดยไม่ต้องเปิด IDE และถ้าพวกเขาใช้งาน OS X ได้เพียงแค่นี้ ยินดีต้อนรับสู่เกม dev พวกเขาสามารถส่งสไปรต์ของพวกเขาและรอ XNB ที่มุ่งมั่นต่อไป
michael.bartnett

มันไม่ใช่เรื่องใหญ่อะไร แต่เป็นเรื่องเจ็บปวด แต่ฉันเดาว่ามันจะต้องทำ ขอบคุณทุกคนสำหรับคำตอบ / ความคิดเห็นของคุณ!
krolth

1

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

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

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


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

นอกจากนี้Texture2D.FromStreamไม่รองรับการโหลด.BMPไฟล์ในขณะที่ไปป์ไลน์เนื้อหา นี่คือสิ่งที่อาจจะโยนคุณออกถ้าคุณใช้ใด ๆสินทรัพย์ก่อนหน้านี้และจากนั้นเปลี่ยนไป.BMP Texture2D.FromStreamฉันยังมีวิธีแก้ปัญหาสำหรับข้อ จำกัด นั้น ฉันจะไปข้างหน้าและโพสต์
David Gouveia

0

ลองดูโครงการนี้สิ

มันจะช่วยให้ศิลปินของคุณสร้าง XNB จากอะไรก็ได้ที่ XNA content Pipeline สนับสนุนเริ่มต้น เฟรมเวิร์กการกระจาย XNA ยังคงเป็นสิ่งที่จำเป็นแม้ว่าศิลปินของคุณไม่ต้องการ Visual Studio


ขอบคุณสำหรับตัวชี้ ดูโค้ดดูเหมือนว่าเป็นการดัดแปลงตัวอย่าง Microsoft ที่ฉันอ้างอิง ขึ้นอยู่กับการติดตั้ง XNA Game Studio เต็มรูปแบบ (ดู ContentBuilder.cs) ทำไมคุณถึงคิดว่ามันไม่?
krolth

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