2013-08-19 35 views
2

我想完成一些東西,我認爲在Windows上的MonoGame GL應該是相當簡單的。那就是從PNG文件加載紋理並將它作爲精靈。到目前爲止,我遇到了很多麻煩。我加載PNG到一個Texture2D用下面的代碼(F#):透明度問題從Monogame PNG加載紋理

use file = System.IO.File.OpenRead("testTexture.png") 
    this.texture <- Texture2D.FromStream(this.GraphicsDevice, file) 

,然後用渲染:

this.spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied); 
    this.spriteBatch.Draw(this.texture, Vector2.Zero, Color.White) 
    this.spriteBatch.End() 

的問題是某種與alpha通道怪異的效果,如如果出現了某些不是alpha預先倍頻的頻道或某些東西,但是我不能確切地確定發生了什麼。但值得注意的是,完全相同的代碼使用官方XNA庫完美呈現。這個問題只出現在我用3.0和3.2版測試的MonoGame中,兩者都有相同的問題。

這裏是在MonoGame PNG渲染測試來說明問題:

http://i.imgur.com/Dny26gI.png

每幀圖像的背景是矢車菊藍,紅,然後,綠色和藍色分別純淨。注意紅色背景的圖像,可以看到紋理中紅線周圍的黑色輪廓。這個輪廓不應該在那裏,因爲線條和背景都是純紅的。請注意,藍色背景圖像中的藍色線條周圍會出現同樣的情況,但在具有綠色背景的圖像中會出現而不是。在該圖像中,綠線與綠色背景融爲一體。

下面是如何使用官方XNA庫完全相同的文件呈現。

http://i.imgur.com/2Rtqhuk.png

通知的藍色,綠色和紅色的線是如何融入到後臺時,背景是相同的顏色。這是正確的行爲。

鑑於相同的代碼在XNA和MonoGame中的行爲不同,我相信框架中必須存在一個錯誤。任何人都可以猜測錯誤的來源和性質?如果這是一個簡單的解決方案,那麼最好的解決方案可能是自己修復該錯誤。

除此之外,雖然我真的只是想學習一種方式,我可以簡單地加載一個PNG並將其正確地呈現在MonoGame中的屏幕上。我相信我不能成爲第一個想做這件事的人。我想盡可能避免內容管道,只是爲了簡單起見。

更新

我做了一些更多的挖掘,試圖找出這個問題的本質。我已經更改了testTexture.png文件,以更好地揭示alpha混合問題。使用這個新的紋理文件後,我截取了不正確的MonoGame渲染的截圖,並在其單獨的顏色通道中查看它。發生了什麼事情讓我感到非常困惑。我最初雖然可能是BlendState.NonPremultiplied被忽略的簡單情況,但我所看到的看起來更加複雜。除此之外,綠色通道似乎與藍色和紅色通道不同地混合。這裏有一個相當大的PNG圖像,這是一個關於我在說什麼的屏幕截圖和解釋彙編:

i.imgur.com/CEUQqm0。png

很明顯,Windows GL的MonoGame中存在某種錯誤,可能還有其他版本我沒有試過(儘管我有興趣看到驗證)。如果有人認爲他們知道可能發生的事情,請告訴我。

最後,這裏的項目文件複製我有問題:

mega.co.nz/#!llFxBbrb!OrpPIn4Tu2UaHHuoSPL03nqOtAJFK59cfxI5TDzLyYI

+0

我的第一個猜測將一直在SpriteBatch.Begin呼叫使用BlendState.NonPremultiplied,但我看到你已經在這樣做。嘗試更改爲SpriteSortMode.Deferred並查看會發生什麼。無論如何,我同意這可能是MonoGame中的一個錯誤。 – craftworkgames

+0

@craftworkgames試過了,但沒有區別:(。但是謝謝。 – battlebottle

回答

6

此問題已得到解決。 MonoGame.Framework/Graphics/ImageEx.cs在下面的方法:在框架中的錯誤是在發現

internal static void RGBToBGR(this Image bmp) 
{ 
    System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes(); 
    System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(rgbtobgr); 

    ia.SetColorMatrix(cm); 
    using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp)) 
    { 
     g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, bmp.Width, bmp.Height, System.Drawing.GraphicsUnit.Pixel, ia); 
    } 
} 

它改變這種修復該問題:

internal static void RGBToBGR(this Image bmp) 
{ 
    using (Bitmap bmpCopy = (Bitmap)bmp.Clone()) 
    { 
     System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes(); 
     System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(rgbtobgr); 

     ia.SetColorMatrix(cm); 
     using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp)) 
     { 
      g.Clear(Color.Transparent); 
      g.DrawImage(bmpCopy, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, bmp.Width, bmp.Height, System.Drawing.GraphicsUnit.Pixel, ia); 
     } 
    } 
} 

發生了什麼事時執行的RGBToBGR轉換,它吸引的是轉換後的圖像對象頂部的圖像版本。這是什麼導致了奇怪的效果。據我所知唯一要做的就是在再次繪製圖像對象之前清除圖像對象,這當然意味着要轉換的位圖必須被複制,以便您可以在複製版本中讀取原始版本剛被清除。

感謝dellis1972查找有關此指着我在正確的方向:https://github.com/mono/MonoGame/issues/1946